blob: 246d34e9b6f913ef42b0861611e3ad96d6788113 [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"
23#include "effects/GrConstColorProcessor.h"
egdaniel64c47282015-11-13 06:54:19 -080024#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080025#include "glsl/GrGLSLFragmentShaderBuilder.h"
ethannicholas417011c2015-11-09 06:35:12 -080026#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080027#include "glsl/GrGLSLUniformHandler.h"
ethannicholas417011c2015-11-09 06:35:12 -080028#endif
29
30static const int kBlockSize = 256;
31static const int kBlockMask = kBlockSize - 1;
32static const int kPerlinNoise = 4096;
33static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
34
Herb Derby99d47212017-01-31 15:30:44 -050035static uint8_t improved_noise_permutations[] = {
36 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
37 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
38 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
39 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
40 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
41 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
42 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
43 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
44 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
45 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
46 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
47 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
48 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 -080049 141, 128, 195, 78, 66, 215, 61, 156, 180,
Herb Derby99d47212017-01-31 15:30:44 -050050 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
51 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
52 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
53 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
54 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
55 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
56 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
57 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
58 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
59 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
60 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
61 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
62 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 -080063 141, 128, 195, 78, 66, 215, 61, 156, 180
64};
65
66namespace {
67
68// noiseValue is the color component's value (or color)
69// limitValue is the maximum perlin noise array index value allowed
70// newValue is the current noise dimension (either width or height)
71inline int checkNoise(int noiseValue, int limitValue, int newValue) {
72 // If the noise value would bring us out of bounds of the current noise array while we are
73 // stiching noise tiles together, wrap the noise around the current dimension of the noise to
74 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
75 if (noiseValue >= limitValue) {
76 noiseValue -= newValue;
77 }
78 return noiseValue;
79}
80
81inline SkScalar smoothCurve(SkScalar t) {
Mike Reeddf85c382017-02-14 10:59:19 -050082 return t * t * (3 - 2 * t);
ethannicholas417011c2015-11-09 06:35:12 -080083}
84
85} // end namespace
86
87struct SkPerlinNoiseShader2::StitchData {
88 StitchData()
89 : fWidth(0)
90 , fWrapX(0)
91 , fHeight(0)
92 , fWrapY(0)
93 {}
94
95 bool operator==(const StitchData& other) const {
96 return fWidth == other.fWidth &&
97 fWrapX == other.fWrapX &&
98 fHeight == other.fHeight &&
99 fWrapY == other.fWrapY;
100 }
101
102 int fWidth; // How much to subtract to wrap for stitching.
103 int fWrapX; // Minimum value to wrap.
104 int fHeight;
105 int fWrapY;
106};
107
108struct SkPerlinNoiseShader2::PaintingData {
109 PaintingData(const SkISize& tileSize, SkScalar seed,
110 SkScalar baseFrequencyX, SkScalar baseFrequencyY,
111 const SkMatrix& matrix)
112 {
113 SkVector vec[2] = {
114 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) },
115 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) },
116 };
117 matrix.mapVectors(vec, 2);
118
119 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
120 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
121 this->init(seed);
122 if (!fTileSize.isEmpty()) {
123 this->stitch();
124 }
125
126#if SK_SUPPORT_GPU
127 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
128 fPermutationsBitmap.setPixels(fLatticeSelector);
129
130 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
131 fNoiseBitmap.setPixels(fNoise[0][0]);
132
133 fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1));
134 fImprovedPermutationsBitmap.setPixels(improved_noise_permutations);
135
136 fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1));
137 static uint8_t gradients[] = { 2, 2, 1, 0,
Herb Derby99d47212017-01-31 15:30:44 -0500138 0, 2, 1, 0,
139 2, 0, 1, 0,
140 0, 0, 1, 0,
141 2, 1, 2, 0,
142 0, 1, 2, 0,
143 2, 1, 0, 0,
144 0, 1, 0, 0,
145 1, 2, 2, 0,
146 1, 0, 2, 0,
147 1, 2, 0, 0,
148 1, 0, 0, 0,
149 2, 2, 1, 0,
150 1, 0, 2, 0,
151 0, 2, 1, 0,
ethannicholas417011c2015-11-09 06:35:12 -0800152 1, 0, 0, 0 };
153 fGradientBitmap.setPixels(gradients);
154#endif
155 }
156
157 int fSeed;
158 uint8_t fLatticeSelector[kBlockSize];
159 uint16_t fNoise[4][kBlockSize][2];
160 SkPoint fGradient[4][kBlockSize];
161 SkISize fTileSize;
162 SkVector fBaseFrequency;
163 StitchData fStitchDataInit;
164
165private:
166
167#if SK_SUPPORT_GPU
168 SkBitmap fPermutationsBitmap;
169 SkBitmap fNoiseBitmap;
170 SkBitmap fImprovedPermutationsBitmap;
171 SkBitmap fGradientBitmap;
172#endif
173
174 inline int random() {
175 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
176 static const int gRandQ = 127773; // m / a
177 static const int gRandR = 2836; // m % a
178
179 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
180 if (result <= 0)
181 result += kRandMaximum;
182 fSeed = result;
183 return result;
184 }
185
186 // Only called once. Could be part of the constructor.
187 void init(SkScalar seed)
188 {
189 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
190
191 // According to the SVG spec, we must truncate (not round) the seed value.
192 fSeed = SkScalarTruncToInt(seed);
193 // The seed value clamp to the range [1, kRandMaximum - 1].
194 if (fSeed <= 0) {
195 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
196 }
197 if (fSeed > kRandMaximum - 1) {
198 fSeed = kRandMaximum - 1;
199 }
200 for (int channel = 0; channel < 4; ++channel) {
201 for (int i = 0; i < kBlockSize; ++i) {
202 fLatticeSelector[i] = i;
203 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
204 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
205 }
206 }
207 for (int i = kBlockSize - 1; i > 0; --i) {
208 int k = fLatticeSelector[i];
209 int j = random() % kBlockSize;
210 SkASSERT(j >= 0);
211 SkASSERT(j < kBlockSize);
212 fLatticeSelector[i] = fLatticeSelector[j];
213 fLatticeSelector[j] = k;
214 }
215
216 // Perform the permutations now
217 {
218 // Copy noise data
219 uint16_t noise[4][kBlockSize][2];
220 for (int i = 0; i < kBlockSize; ++i) {
221 for (int channel = 0; channel < 4; ++channel) {
222 for (int j = 0; j < 2; ++j) {
223 noise[channel][i][j] = fNoise[channel][i][j];
224 }
225 }
226 }
227 // Do permutations on noise data
228 for (int i = 0; i < kBlockSize; ++i) {
229 for (int channel = 0; channel < 4; ++channel) {
230 for (int j = 0; j < 2; ++j) {
231 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
232 }
233 }
234 }
235 }
236
237 // Half of the largest possible value for 16 bit unsigned int
238 static const SkScalar gHalfMax16bits = 32767.5f;
239
240 // Compute gradients from permutated noise data
241 for (int channel = 0; channel < 4; ++channel) {
242 for (int i = 0; i < kBlockSize; ++i) {
243 fGradient[channel][i] = SkPoint::Make(
Mike Reeddf85c382017-02-14 10:59:19 -0500244 (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef,
245 (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef);
ethannicholas417011c2015-11-09 06:35:12 -0800246 fGradient[channel][i].normalize();
247 // Put the normalized gradient back into the noise data
Mike Reeddf85c382017-02-14 10:59:19 -0500248 fNoise[channel][i][0] = SkScalarRoundToInt(
249 (fGradient[channel][i].fX + 1) * gHalfMax16bits);
250 fNoise[channel][i][1] = SkScalarRoundToInt(
251 (fGradient[channel][i].fY + 1) * gHalfMax16bits);
ethannicholas417011c2015-11-09 06:35:12 -0800252 }
253 }
254 }
255
256 // Only called once. Could be part of the constructor.
257 void stitch() {
258 SkScalar tileWidth = SkIntToScalar(fTileSize.width());
259 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
260 SkASSERT(tileWidth > 0 && tileHeight > 0);
261 // When stitching tiled turbulence, the frequencies must be adjusted
262 // so that the tile borders will be continuous.
263 if (fBaseFrequency.fX) {
264 SkScalar lowFrequencx =
265 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
266 SkScalar highFrequencx =
267 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
268 // BaseFrequency should be non-negative according to the standard.
269 if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
270 fBaseFrequency.fX = lowFrequencx;
271 } else {
272 fBaseFrequency.fX = highFrequencx;
273 }
274 }
275 if (fBaseFrequency.fY) {
276 SkScalar lowFrequency =
277 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
278 SkScalar highFrequency =
279 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
280 if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
281 fBaseFrequency.fY = lowFrequency;
282 } else {
283 fBaseFrequency.fY = highFrequency;
284 }
285 }
286 // Set up TurbulenceInitial stitch values.
287 fStitchDataInit.fWidth =
288 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
289 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
290 fStitchDataInit.fHeight =
291 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
292 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
293 }
294
295public:
296
297#if SK_SUPPORT_GPU
298 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
299
300 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
301
302 const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; }
303
304 const SkBitmap& getGradientBitmap() const { return fGradientBitmap; }
305#endif
306};
307
reed8a21c9f2016-03-08 18:50:00 -0800308sk_sp<SkShader> SkPerlinNoiseShader2::MakeFractalNoise(SkScalar baseFrequencyX,
309 SkScalar baseFrequencyY,
310 int numOctaves, SkScalar seed,
311 const SkISize* tileSize) {
312 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX,
313 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800314}
315
reed8a21c9f2016-03-08 18:50:00 -0800316sk_sp<SkShader> SkPerlinNoiseShader2::MakeTurbulence(SkScalar baseFrequencyX,
317 SkScalar baseFrequencyY,
318 int numOctaves, SkScalar seed,
319 const SkISize* tileSize) {
320 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX,
321 baseFrequencyY, numOctaves, seed, tileSize));
ethannicholas417011c2015-11-09 06:35:12 -0800322}
323
reed8a21c9f2016-03-08 18:50:00 -0800324sk_sp<SkShader> SkPerlinNoiseShader2::MakeImprovedNoise(SkScalar baseFrequencyX,
325 SkScalar baseFrequencyY,
326 int numOctaves, SkScalar z) {
327 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX,
328 baseFrequencyY, numOctaves, z, NULL));
ethannicholas417011c2015-11-09 06:35:12 -0800329}
330
331SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
332 SkScalar baseFrequencyX,
333 SkScalar baseFrequencyY,
334 int numOctaves,
335 SkScalar seed,
336 const SkISize* tileSize)
337 : fType(type)
338 , fBaseFrequencyX(baseFrequencyX)
339 , fBaseFrequencyY(baseFrequencyY)
340 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
341 , fSeed(seed)
342 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
343 , fStitchTiles(!fTileSize.isEmpty())
344{
345 SkASSERT(numOctaves >= 0 && numOctaves < 256);
346}
347
348SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
349}
350
reed60c9b582016-04-03 09:11:13 -0700351sk_sp<SkFlattenable> SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
ethannicholas417011c2015-11-09 06:35:12 -0800352 Type type = (Type)buffer.readInt();
353 SkScalar freqX = buffer.readScalar();
354 SkScalar freqY = buffer.readScalar();
355 int octaves = buffer.readInt();
356 SkScalar seed = buffer.readScalar();
357 SkISize tileSize;
358 tileSize.fWidth = buffer.readInt();
359 tileSize.fHeight = buffer.readInt();
360
361 switch (type) {
362 case kFractalNoise_Type:
reed60c9b582016-04-03 09:11:13 -0700363 return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800364 case kTurbulence_Type:
reed60c9b582016-04-03 09:11:13 -0700365 return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed, &tileSize);
ethannicholas417011c2015-11-09 06:35:12 -0800366 case kImprovedNoise_Type:
reed60c9b582016-04-03 09:11:13 -0700367 return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed);
ethannicholas417011c2015-11-09 06:35:12 -0800368 default:
369 return nullptr;
370 }
371}
372
373void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
374 buffer.writeInt((int) fType);
375 buffer.writeScalar(fBaseFrequencyX);
376 buffer.writeScalar(fBaseFrequencyY);
377 buffer.writeInt(fNumOctaves);
378 buffer.writeScalar(fSeed);
379 buffer.writeInt(fTileSize.fWidth);
380 buffer.writeInt(fTileSize.fHeight);
381}
382
383SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
384 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
385 struct Noise {
386 int noisePositionIntegerValue;
387 int nextNoisePositionIntegerValue;
388 SkScalar noisePositionFractionValue;
389 Noise(SkScalar component)
390 {
391 SkScalar position = component + kPerlinNoise;
392 noisePositionIntegerValue = SkScalarFloorToInt(position);
393 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
394 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
395 }
396 };
397 Noise noiseX(noiseVector.x());
398 Noise noiseY(noiseVector.y());
399 SkScalar u, v;
400 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
401 // If stitching, adjust lattice points accordingly.
402 if (perlinNoiseShader.fStitchTiles) {
403 noiseX.noisePositionIntegerValue =
404 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
405 noiseY.noisePositionIntegerValue =
406 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
407 noiseX.nextNoisePositionIntegerValue =
408 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
409 noiseY.nextNoisePositionIntegerValue =
410 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
411 }
412 noiseX.noisePositionIntegerValue &= kBlockMask;
413 noiseY.noisePositionIntegerValue &= kBlockMask;
414 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
415 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
416 int i =
417 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
418 int j =
419 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
420 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
421 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
422 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
423 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
424 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
425 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
426 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
427 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
428 noiseY.noisePositionFractionValue); // Offset (0,0)
429 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
430 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
431 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
432 SkScalar a = SkScalarInterp(u, v, sx);
433 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
434 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
435 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
436 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
437 SkScalar b = SkScalarInterp(u, v, sx);
438 return SkScalarInterp(a, b, sy);
439}
440
441SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
442 int channel, StitchData& stitchData, const SkPoint& point) const {
443 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
444 if (perlinNoiseShader.fStitchTiles) {
445 // Set up TurbulenceInitial stitch values.
446 stitchData = fPaintingData->fStitchDataInit;
447 }
448 SkScalar turbulenceFunctionResult = 0;
Mike Reeddf85c382017-02-14 10:59:19 -0500449 SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData->fBaseFrequency.fX,
450 point.y() * fPaintingData->fBaseFrequency.fY));
ethannicholas417011c2015-11-09 06:35:12 -0800451 SkScalar ratio = SK_Scalar1;
452 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
453 SkScalar noise = noise2D(channel, stitchData, noiseVector);
454 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
455 noise : SkScalarAbs(noise);
456 turbulenceFunctionResult += numer / ratio;
457 noiseVector.fX *= 2;
458 noiseVector.fY *= 2;
459 ratio *= 2;
460 if (perlinNoiseShader.fStitchTiles) {
461 // Update stitch values
462 stitchData.fWidth *= 2;
463 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
464 stitchData.fHeight *= 2;
465 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
466 }
467 }
468
469 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
470 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
471 if (perlinNoiseShader.fType == kFractalNoise_Type) {
Mike Reeddf85c382017-02-14 10:59:19 -0500472 turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1);
ethannicholas417011c2015-11-09 06:35:12 -0800473 }
474
475 if (channel == 3) { // Scale alpha by paint value
476 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
477 }
478
479 // Clamp result
480 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
481}
482
483////////////////////////////////////////////////////////////////////////////////////////////////////
484// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
Herb Derby99d47212017-01-31 15:30:44 -0500485static SkScalar fade(SkScalar t) {
486 return t * t * t * (t * (t * 6 - 15) + 10);
ethannicholas417011c2015-11-09 06:35:12 -0800487}
488
Herb Derby99d47212017-01-31 15:30:44 -0500489static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
490 return a + t * (b - a);
ethannicholas417011c2015-11-09 06:35:12 -0800491}
492
493static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
494 int h = hash & 15;
495 SkScalar u = h < 8 ? x : y;
496 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
497 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
498}
499
500SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
501 int channel, const SkPoint& point) const {
502 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
503 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
504 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
505 // z offset between different channels, chosen arbitrarily
506 static const SkScalar CHANNEL_DELTA = 1000.0f;
507 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
508 SkScalar result = 0;
509 SkScalar ratio = SK_Scalar1;
510 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
511 int X = SkScalarFloorToInt(x) & 255;
512 int Y = SkScalarFloorToInt(y) & 255;
513 int Z = SkScalarFloorToInt(z) & 255;
514 SkScalar px = x - SkScalarFloorToScalar(x);
515 SkScalar py = y - SkScalarFloorToScalar(y);
516 SkScalar pz = z - SkScalarFloorToScalar(z);
517 SkScalar u = fade(px);
518 SkScalar v = fade(py);
519 SkScalar w = fade(pz);
520 uint8_t* permutations = improved_noise_permutations;
521 int A = permutations[X] + Y;
522 int AA = permutations[A] + Z;
523 int AB = permutations[A + 1] + Z;
524 int B = permutations[X + 1] + Y;
525 int BA = permutations[B] + Z;
526 int BB = permutations[B + 1] + Z;
527 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
528 grad(permutations[BA ], px - 1, py , pz )),
529 lerp(u, grad(permutations[AB ], px , py - 1, pz ),
530 grad(permutations[BB ], px - 1, py - 1, pz ))),
531 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
532 grad(permutations[BA + 1], px - 1, py , pz - 1)),
533 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
534 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
535 ratio;
536 x *= 2;
537 y *= 2;
538 ratio *= 2;
539 }
540 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
541 return result;
542}
543////////////////////////////////////////////////////////////////////////////////////////////////////
544
545SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
546 const SkPoint& point, StitchData& stitchData) const {
547 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
548 SkPoint newPoint;
549 fMatrix.mapPoints(&newPoint, &point, 1);
550 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
551 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
552
553 U8CPU rgba[4];
554 for (int channel = 3; channel >= 0; --channel) {
555 SkScalar value;
556 if (perlinNoiseShader.fType == kImprovedNoise_Type) {
557 value = calculateImprovedNoiseValueForPoint(channel, newPoint);
558 }
559 else {
560 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
561 }
562 rgba[channel] = SkScalarFloorToInt(255 * value);
563 }
564 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
565}
566
Herb Derby83e939b2017-02-07 14:25:11 -0500567SkShader::Context* SkPerlinNoiseShader2::onMakeContext(const ContextRec& rec,
568 SkArenaAlloc* alloc) const {
569 return alloc->make<PerlinNoiseShaderContext>(*this, rec);
ethannicholas417011c2015-11-09 06:35:12 -0800570}
571
572SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
573 const SkPerlinNoiseShader2& shader, const ContextRec& rec)
574 : INHERITED(shader, rec)
575{
576 SkMatrix newMatrix = *rec.fMatrix;
577 newMatrix.preConcat(shader.getLocalMatrix());
578 if (rec.fLocalMatrix) {
579 newMatrix.preConcat(*rec.fLocalMatrix);
580 }
581 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
582 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
583 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
584 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
585 shader.fBaseFrequencyY, newMatrix);
586}
587
588SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
589
590void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
591 int x, int y, SkPMColor result[], int count) {
592 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
593 StitchData stitchData;
594 for (int i = 0; i < count; ++i) {
595 result[i] = shade(point, stitchData);
596 point.fX += SK_Scalar1;
597 }
598}
599
ethannicholas417011c2015-11-09 06:35:12 -0800600/////////////////////////////////////////////////////////////////////
601
602#if SK_SUPPORT_GPU
603
egdaniel64c47282015-11-13 06:54:19 -0800604class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -0800605public:
robertphillipsbf536af2016-02-04 06:11:53 -0800606 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -0800607
Brian Salomon94efbf52016-11-29 13:43:05 -0500608 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
ethannicholas417011c2015-11-09 06:35:12 -0800609
610protected:
611 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
612
613private:
ethannicholas417011c2015-11-09 06:35:12 -0800614 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
ethannicholas417011c2015-11-09 06:35:12 -0800615 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
616
egdaniel64c47282015-11-13 06:54:19 -0800617 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -0800618};
619
620/////////////////////////////////////////////////////////////////////
621
622class GrPerlinNoise2Effect : public GrFragmentProcessor {
623public:
Brian Osman32342f02017-03-04 08:12:46 -0500624 static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500625 SkPerlinNoiseShader2::Type type,
bungeman06ca8ec2016-06-09 08:01:03 -0700626 int numOctaves, bool stitchTiles,
627 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500628 sk_sp<GrTextureProxy> permutationsProxy,
629 sk_sp<GrTextureProxy> noiseProxy,
bungeman06ca8ec2016-06-09 08:01:03 -0700630 const SkMatrix& matrix) {
631 return sk_sp<GrFragmentProcessor>(
Brian Osman32342f02017-03-04 08:12:46 -0500632 new GrPerlinNoise2Effect(resourceProvider, type, numOctaves, stitchTiles, paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500633 std::move(permutationsProxy), std::move(noiseProxy), matrix));
ethannicholas417011c2015-11-09 06:35:12 -0800634 }
635
636 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
637
638 const char* name() const override { return "PerlinNoise"; }
639
640 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
641
642 SkPerlinNoiseShader2::Type type() const { return fType; }
643 bool stitchTiles() const { return fStitchTiles; }
644 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
645 int numOctaves() const { return fNumOctaves; }
646 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
647
648private:
egdaniel57d3b032015-11-13 11:57:27 -0800649 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800650 return new GrGLPerlinNoise2;
ethannicholas417011c2015-11-09 06:35:12 -0800651 }
652
Brian Salomon94efbf52016-11-29 13:43:05 -0500653 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800654 GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -0800655 GrGLPerlinNoise2::GenKey(*this, caps, b);
656 }
657
658 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
659 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
660 return fType == s.fType &&
661 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
662 fNumOctaves == s.fNumOctaves &&
663 fStitchTiles == s.fStitchTiles &&
664 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
665 }
666
Brian Osman32342f02017-03-04 08:12:46 -0500667 GrPerlinNoise2Effect(GrResourceProvider* resourceProvider,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500668 SkPerlinNoiseShader2::Type type, int numOctaves, bool stitchTiles,
Brian Salomon587e08f2017-01-27 10:59:27 -0500669 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -0500670 sk_sp<GrTextureProxy> permutationsProxy,
671 sk_sp<GrTextureProxy> noiseProxy,
Brian Salomon587e08f2017-01-27 10:59:27 -0500672 const SkMatrix& matrix)
673 : INHERITED(kNone_OptimizationFlags)
674 , fType(type)
675 , fNumOctaves(numOctaves)
676 , fStitchTiles(stitchTiles)
Brian Osman32342f02017-03-04 08:12:46 -0500677 , fPermutationsSampler(resourceProvider, std::move(permutationsProxy))
678 , fNoiseSampler(resourceProvider, std::move(noiseProxy))
Brian Salomon587e08f2017-01-27 10:59:27 -0500679 , fPaintingData(paintingData) {
ethannicholas417011c2015-11-09 06:35:12 -0800680 this->initClassID<GrPerlinNoise2Effect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -0500681 this->addTextureSampler(&fPermutationsSampler);
682 this->addTextureSampler(&fNoiseSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -0400683 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -0800684 this->addCoordTransform(&fCoordTransform);
685 }
686
687 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
688
Brian Salomon0bbecb22016-11-17 11:38:22 -0500689 SkPerlinNoiseShader2::Type fType;
690 GrCoordTransform fCoordTransform;
691 int fNumOctaves;
692 bool fStitchTiles;
693 TextureSampler fPermutationsSampler;
694 TextureSampler fNoiseSampler;
695 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -0800696
ethannicholas417011c2015-11-09 06:35:12 -0800697 typedef GrFragmentProcessor INHERITED;
698};
699
700/////////////////////////////////////////////////////////////////////
701GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
702
Hal Canary6f6961e2017-01-31 13:50:44 -0500703#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700704sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -0800705 int numOctaves = d->fRandom->nextRangeU(2, 10);
706 bool stitchTiles = d->fRandom->nextBool();
707 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
708 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
709 d->fRandom->nextRangeU(4, 4096));
710 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
711 0.99f);
712 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
713 0.99f);
714
reed8a21c9f2016-03-08 18:50:00 -0800715 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
716 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
717 stitchTiles ? &tileSize : nullptr) :
718 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
ethannicholas417011c2015-11-09 06:35:12 -0800719 stitchTiles ? &tileSize : nullptr));
720
Brian Osman9f532a32016-10-19 11:12:09 -0400721 GrTest::TestAsFPArgs asFPArgs(d);
722 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -0800723}
Hal Canary6f6961e2017-01-31 13:50:44 -0500724#endif
ethannicholas417011c2015-11-09 06:35:12 -0800725
ethannicholas417011c2015-11-09 06:35:12 -0800726void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
robertphillipsd3b32bf2016-02-05 07:15:39 -0800727 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
728
egdaniel4ca2e602015-11-18 08:01:26 -0800729 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -0800730 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -0700731 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -0800732
cdalton5e58cee2016-02-11 12:49:47 -0800733 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800734 kVec2f_GrSLType, kDefault_GrSLPrecision,
735 "baseFrequency");
736 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -0800737
738 const char* stitchDataUni = nullptr;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800739 if (pne.stitchTiles()) {
cdalton5e58cee2016-02-11 12:49:47 -0800740 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800741 kVec2f_GrSLType, kDefault_GrSLPrecision,
742 "stitchData");
743 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
ethannicholas417011c2015-11-09 06:35:12 -0800744 }
745
746 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
747 const char* chanCoordR = "0.125";
748 const char* chanCoordG = "0.375";
749 const char* chanCoordB = "0.625";
750 const char* chanCoordA = "0.875";
751 const char* chanCoord = "chanCoord";
752 const char* stitchData = "stitchData";
753 const char* ratio = "ratio";
754 const char* noiseVec = "noiseVec";
755 const char* noiseSmooth = "noiseSmooth";
756 const char* floorVal = "floorVal";
757 const char* fractVal = "fractVal";
758 const char* uv = "uv";
759 const char* ab = "ab";
760 const char* latticeIdx = "latticeIdx";
761 const char* bcoords = "bcoords";
762 const char* lattice = "lattice";
763 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
764 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
765 // [-1,1] vector and perform a dot product between that vector and the provided vector.
766 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
767
768 // Add noise function
Brian Salomon99938a82016-11-21 13:41:08 -0500769 static const GrShaderVar gPerlinNoiseArgs[] = {
770 GrShaderVar(chanCoord, kFloat_GrSLType),
771 GrShaderVar(noiseVec, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800772 };
773
Brian Salomon99938a82016-11-21 13:41:08 -0500774 static const GrShaderVar gPerlinNoiseStitchArgs[] = {
775 GrShaderVar(chanCoord, kFloat_GrSLType),
776 GrShaderVar(noiseVec, kVec2f_GrSLType),
777 GrShaderVar(stitchData, kVec2f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -0800778 };
779
780 SkString noiseCode;
781
782 noiseCode.appendf("\tvec4 %s;\n", floorVal);
783 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
784 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
785 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
786
787 // smooth curve : t * t * (3 - 2 * t)
788 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
789 noiseSmooth, fractVal, fractVal, fractVal);
790
791 // Adjust frequencies if we're stitching tiles
robertphillipsd3b32bf2016-02-05 07:15:39 -0800792 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800793 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
794 floorVal, stitchData, floorVal, stitchData);
795 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
796 floorVal, stitchData, floorVal, stitchData);
797 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
798 floorVal, stitchData, floorVal, stitchData);
799 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
800 floorVal, stitchData, floorVal, stitchData);
801 }
802
803 // Get texture coordinates and normalize
804 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
805 floorVal, floorVal);
806
807 // Get permutation for x
808 {
809 SkString xCoords("");
810 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
811
812 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700813 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800814 kVec2f_GrSLType);
815 noiseCode.append(".r;");
816 }
817
818 // Get permutation for x + 1
819 {
820 SkString xCoords("");
821 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
822
823 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
cdalton3f6f76f2016-04-11 12:18:09 -0700824 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800825 kVec2f_GrSLType);
826 noiseCode.append(".r;");
827 }
828
829#if defined(SK_BUILD_FOR_ANDROID)
830 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
831 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
832 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
833 // (or 0.484368 here). The following rounding operation prevents these precision issues from
834 // affecting the result of the noise by making sure that we only have multiples of 1/255.
835 // (Note that 1/255 is about 0.003921569, which is the value used here).
836 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
837 latticeIdx, latticeIdx);
838#endif
839
840 // Get (x,y) coordinates with the permutated x
841 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
842
843 noiseCode.appendf("\n\n\tvec2 %s;", uv);
844 // Compute u, at offset (0,0)
845 {
846 SkString latticeCoords("");
847 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
848 noiseCode.appendf("\n\tvec4 %s = ", lattice);
cdalton3f6f76f2016-04-11 12:18:09 -0700849 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800850 kVec2f_GrSLType);
851 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
852 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
853 }
854
855 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
856 // Compute v, at offset (-1,0)
857 {
858 SkString latticeCoords("");
859 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
860 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700861 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800862 kVec2f_GrSLType);
863 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
864 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
865 }
866
867 // Compute 'a' as a linear interpolation of 'u' and 'v'
868 noiseCode.appendf("\n\tvec2 %s;", ab);
869 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
870
871 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
872 // Compute v, at offset (-1,-1)
873 {
874 SkString latticeCoords("");
875 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
876 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700877 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800878 kVec2f_GrSLType);
879 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
880 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
881 }
882
883 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
884 // Compute u, at offset (0,-1)
885 {
886 SkString latticeCoords("");
887 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
888 noiseCode.append("\n\tlattice = ");
cdalton3f6f76f2016-04-11 12:18:09 -0700889 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -0800890 kVec2f_GrSLType);
891 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
892 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
893 }
894
895 // Compute 'b' as a linear interpolation of 'u' and 'v'
896 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
897 // Compute the noise as a linear interpolation of 'a' and 'b'
898 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
899
900 SkString noiseFuncName;
robertphillipsd3b32bf2016-02-05 07:15:39 -0800901 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800902 fsBuilder->emitFunction(kFloat_GrSLType,
903 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
904 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
905 } else {
906 fsBuilder->emitFunction(kFloat_GrSLType,
907 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
908 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
909 }
910
911 // There are rounding errors if the floor operation is not performed here
912 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
913 noiseVec, vCoords.c_str(), baseFrequencyUni);
914
915 // Clear the color accumulator
916 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
917
robertphillipsd3b32bf2016-02-05 07:15:39 -0800918 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800919 // Set up TurbulenceInitial stitch values.
920 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
921 }
922
923 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
924
925 // Loop over all octaves
robertphillipsd3b32bf2016-02-05 07:15:39 -0800926 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
ethannicholas417011c2015-11-09 06:35:12 -0800927
928 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
robertphillipsd3b32bf2016-02-05 07:15:39 -0800929 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800930 fsBuilder->codeAppend("abs(");
931 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800932 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800933 fsBuilder->codeAppendf(
934 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
935 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
936 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
937 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
938 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
939 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
940 } else {
941 fsBuilder->codeAppendf(
942 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
943 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
944 noiseFuncName.c_str(), chanCoordR, noiseVec,
945 noiseFuncName.c_str(), chanCoordG, noiseVec,
946 noiseFuncName.c_str(), chanCoordB, noiseVec,
947 noiseFuncName.c_str(), chanCoordA, noiseVec);
948 }
robertphillipsd3b32bf2016-02-05 07:15:39 -0800949 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800950 fsBuilder->codeAppendf(")"); // end of "abs("
951 }
952 fsBuilder->codeAppendf(" * %s;", ratio);
953
954 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
955 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
956
robertphillipsd3b32bf2016-02-05 07:15:39 -0800957 if (pne.stitchTiles()) {
ethannicholas417011c2015-11-09 06:35:12 -0800958 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
959 }
960 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
961
robertphillipsd3b32bf2016-02-05 07:15:39 -0800962 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
ethannicholas417011c2015-11-09 06:35:12 -0800963 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
964 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
965 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
966 args.fOutputColor,args.fOutputColor);
967 }
968
969 // Clamp values
970 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
971
972 // Pre-multiply the result
973 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
974 args.fOutputColor, args.fOutputColor,
975 args.fOutputColor, args.fOutputColor);
976}
977
Brian Salomon94efbf52016-11-29 13:43:05 -0500978void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrShaderCaps&,
egdaniel2d721d32015-11-11 13:06:05 -0800979 GrProcessorKeyBuilder* b) {
ethannicholas417011c2015-11-09 06:35:12 -0800980 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
981
982 uint32_t key = turbulence.numOctaves();
983
984 key = key << 3; // Make room for next 3 bits
985
986 switch (turbulence.type()) {
987 case SkPerlinNoiseShader2::kFractalNoise_Type:
988 key |= 0x1;
989 break;
990 case SkPerlinNoiseShader2::kTurbulence_Type:
991 key |= 0x2;
992 break;
993 default:
994 // leave key at 0
995 break;
996 }
997
998 if (turbulence.stitchTiles()) {
999 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1000 }
1001
1002 b->add32(key);
1003}
1004
1005void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1006 const GrProcessor& processor) {
1007 INHERITED::onSetData(pdman, processor);
1008
1009 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1010
1011 const SkVector& baseFrequency = turbulence.baseFrequency();
1012 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1013
1014 if (turbulence.stitchTiles()) {
1015 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1016 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1017 SkIntToScalar(stitchData.fHeight));
1018 }
1019}
1020
1021/////////////////////////////////////////////////////////////////////
1022
egdaniel64c47282015-11-13 06:54:19 -08001023class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
ethannicholas417011c2015-11-09 06:35:12 -08001024public:
robertphillipsbf536af2016-02-04 06:11:53 -08001025 void emitCode(EmitArgs&) override;
ethannicholas417011c2015-11-09 06:35:12 -08001026
Brian Salomon94efbf52016-11-29 13:43:05 -05001027 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
ethannicholas417011c2015-11-09 06:35:12 -08001028
1029protected:
1030 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1031
1032private:
ethannicholas417011c2015-11-09 06:35:12 -08001033 GrGLSLProgramDataManager::UniformHandle fZUni;
1034 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1035 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1036
egdaniel64c47282015-11-13 06:54:19 -08001037 typedef GrGLSLFragmentProcessor INHERITED;
ethannicholas417011c2015-11-09 06:35:12 -08001038};
1039
1040/////////////////////////////////////////////////////////////////////
1041
1042class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1043public:
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001044 static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider,
1045 int octaves, SkScalar z,
bungeman06ca8ec2016-06-09 08:01:03 -07001046 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001047 sk_sp<GrTextureProxy> permutationsProxy,
1048 sk_sp<GrTextureProxy> gradientProxy,
bungeman06ca8ec2016-06-09 08:01:03 -07001049 const SkMatrix& matrix) {
1050 return sk_sp<GrFragmentProcessor>(
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001051 new GrImprovedPerlinNoiseEffect(resourceProvider, octaves, z, paintingData,
1052 std::move(permutationsProxy),
1053 std::move(gradientProxy), matrix));
ethannicholas417011c2015-11-09 06:35:12 -08001054 }
1055
1056 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1057
1058 const char* name() const override { return "ImprovedPerlinNoise"; }
1059
1060 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1061 SkScalar z() const { return fZ; }
1062 int octaves() const { return fOctaves; }
1063 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1064
1065private:
egdaniel57d3b032015-11-13 11:57:27 -08001066 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
robertphillipsbf536af2016-02-04 06:11:53 -08001067 return new GrGLImprovedPerlinNoise;
ethannicholas417011c2015-11-09 06:35:12 -08001068 }
1069
Brian Salomon94efbf52016-11-29 13:43:05 -05001070 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
ethannicholas417011c2015-11-09 06:35:12 -08001071 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1072 }
1073
1074 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1075 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1076 return fZ == fZ &&
1077 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1078 }
1079
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001080 GrImprovedPerlinNoiseEffect(GrResourceProvider* resourceProvider,
1081 int octaves, SkScalar z,
ethannicholas417011c2015-11-09 06:35:12 -08001082 SkPerlinNoiseShader2::PaintingData* paintingData,
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001083 sk_sp<GrTextureProxy> permutationsProxy,
1084 sk_sp<GrTextureProxy> gradientProxy,
ethannicholas417011c2015-11-09 06:35:12 -08001085 const SkMatrix& matrix)
Brian Salomon587e08f2017-01-27 10:59:27 -05001086 : INHERITED(kNone_OptimizationFlags)
1087 , fOctaves(octaves)
1088 , fZ(z)
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001089 , fPermutationsSampler(resourceProvider, std::move(permutationsProxy))
1090 , fGradientSampler(resourceProvider, std::move(gradientProxy))
Brian Salomon587e08f2017-01-27 10:59:27 -05001091 , fPaintingData(paintingData) {
ethannicholas417011c2015-11-09 06:35:12 -08001092 this->initClassID<GrImprovedPerlinNoiseEffect>();
Brian Salomon0bbecb22016-11-17 11:38:22 -05001093 this->addTextureSampler(&fPermutationsSampler);
1094 this->addTextureSampler(&fGradientSampler);
Brian Salomon2ebd0c82016-10-03 17:15:28 -04001095 fCoordTransform.reset(matrix);
ethannicholas417011c2015-11-09 06:35:12 -08001096 this->addCoordTransform(&fCoordTransform);
1097 }
1098
1099 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1100
Brian Salomon0bbecb22016-11-17 11:38:22 -05001101 GrCoordTransform fCoordTransform;
1102 int fOctaves;
1103 SkScalar fZ;
1104 TextureSampler fPermutationsSampler;
1105 TextureSampler fGradientSampler;
1106 SkPerlinNoiseShader2::PaintingData* fPaintingData;
ethannicholas417011c2015-11-09 06:35:12 -08001107
ethannicholas417011c2015-11-09 06:35:12 -08001108 typedef GrFragmentProcessor INHERITED;
1109};
1110
1111/////////////////////////////////////////////////////////////////////
1112GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1113
Hal Canary6f6961e2017-01-31 13:50:44 -05001114#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -07001115sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
ethannicholas417011c2015-11-09 06:35:12 -08001116 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1117 0.99f);
1118 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1119 0.99f);
1120 int numOctaves = d->fRandom->nextRangeU(2, 10);
1121 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1122
reed8a21c9f2016-03-08 18:50:00 -08001123 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1124 baseFrequencyY,
1125 numOctaves,
1126 z));
ethannicholas417011c2015-11-09 06:35:12 -08001127
Brian Osman9f532a32016-10-19 11:12:09 -04001128 GrTest::TestAsFPArgs asFPArgs(d);
1129 return shader->asFragmentProcessor(asFPArgs.args());
ethannicholas417011c2015-11-09 06:35:12 -08001130}
Hal Canary6f6961e2017-01-31 13:50:44 -05001131#endif
ethannicholas417011c2015-11-09 06:35:12 -08001132
ethannicholas417011c2015-11-09 06:35:12 -08001133void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
egdaniel4ca2e602015-11-18 08:01:26 -08001134 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
egdaniel7ea439b2015-12-03 09:20:44 -08001135 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
bsalomon1a1aa932016-09-12 09:30:36 -07001136 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
ethannicholas417011c2015-11-09 06:35:12 -08001137
cdalton5e58cee2016-02-11 12:49:47 -08001138 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001139 kVec2f_GrSLType, kDefault_GrSLPrecision,
1140 "baseFrequency");
1141 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
ethannicholas417011c2015-11-09 06:35:12 -08001142
cdalton5e58cee2016-02-11 12:49:47 -08001143 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001144 kFloat_GrSLType, kDefault_GrSLPrecision,
1145 "octaves");
1146 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
ethannicholas417011c2015-11-09 06:35:12 -08001147
cdalton5e58cee2016-02-11 12:49:47 -08001148 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001149 kFloat_GrSLType, kDefault_GrSLPrecision,
1150 "z");
1151 const char* zUni = uniformHandler->getUniformCStr(fZUni);
ethannicholas417011c2015-11-09 06:35:12 -08001152
1153 // fade function
Brian Salomon99938a82016-11-21 13:41:08 -05001154 static const GrShaderVar fadeArgs[] = {
1155 GrShaderVar("t", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001156 };
1157 SkString fadeFuncName;
1158 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
Herb Derby99d47212017-01-31 15:30:44 -05001159 fadeArgs,
1160 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
ethannicholas417011c2015-11-09 06:35:12 -08001161 &fadeFuncName);
1162
1163 // perm function
Brian Salomon99938a82016-11-21 13:41:08 -05001164 static const GrShaderVar permArgs[] = {
1165 GrShaderVar("x", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001166 };
1167 SkString permFuncName;
1168 SkString permCode("return ");
Herb Derby99d47212017-01-31 15:30:44 -05001169 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
ethannicholas417011c2015-11-09 06:35:12 -08001170 // sure why. Using fract() (here and the next texture lookup) as a workaround.
cdalton3f6f76f2016-04-11 12:18:09 -07001171 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001172 kVec2f_GrSLType);
1173 permCode.append(".r * 255.0;");
Herb Derby99d47212017-01-31 15:30:44 -05001174 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001175 permCode.c_str(), &permFuncName);
1176
1177 // grad function
Brian Salomon99938a82016-11-21 13:41:08 -05001178 static const GrShaderVar gradArgs[] = {
1179 GrShaderVar("x", kFloat_GrSLType),
1180 GrShaderVar("p", kVec3f_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001181 };
1182 SkString gradFuncName;
1183 SkString gradCode("return dot(");
cdalton3f6f76f2016-04-11 12:18:09 -07001184 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
ethannicholas417011c2015-11-09 06:35:12 -08001185 kVec2f_GrSLType);
1186 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
Herb Derby99d47212017-01-31 15:30:44 -05001187 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001188 gradCode.c_str(), &gradFuncName);
1189
1190 // lerp function
Brian Salomon99938a82016-11-21 13:41:08 -05001191 static const GrShaderVar lerpArgs[] = {
1192 GrShaderVar("a", kFloat_GrSLType),
1193 GrShaderVar("b", kFloat_GrSLType),
1194 GrShaderVar("w", kFloat_GrSLType)
ethannicholas417011c2015-11-09 06:35:12 -08001195 };
1196 SkString lerpFuncName;
Herb Derby99d47212017-01-31 15:30:44 -05001197 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001198 "return a + w * (b - a);", &lerpFuncName);
1199
1200 // noise function
Brian Salomon99938a82016-11-21 13:41:08 -05001201 static const GrShaderVar noiseArgs[] = {
1202 GrShaderVar("p", kVec3f_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001203 };
1204 SkString noiseFuncName;
1205 SkString noiseCode;
1206 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1207 noiseCode.append("p -= floor(p);");
1208 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1209 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1210 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1211 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1212 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1213 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1214 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1215 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001216 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001217 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001218 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001219 permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001220 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001221 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001222 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
ethannicholas417011c2015-11-09 06:35:12 -08001223 gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001224 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1225 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001226 permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001227 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
ethannicholas417011c2015-11-09 06:35:12 -08001228 gradFuncName.c_str(), permFuncName.c_str());
1229 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1230 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
Herb Derby99d47212017-01-31 15:30:44 -05001231 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 -08001232 gradFuncName.c_str(), permFuncName.c_str());
1233 noiseCode.append("return result;");
Herb Derby99d47212017-01-31 15:30:44 -05001234 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
ethannicholas417011c2015-11-09 06:35:12 -08001235 noiseCode.c_str(), &noiseFuncName);
Herb Derby99d47212017-01-31 15:30:44 -05001236
ethannicholas417011c2015-11-09 06:35:12 -08001237 // noiseOctaves function
Brian Salomon99938a82016-11-21 13:41:08 -05001238 static const GrShaderVar noiseOctavesArgs[] = {
1239 GrShaderVar("p", kVec3f_GrSLType),
1240 GrShaderVar("octaves", kFloat_GrSLType),
ethannicholas417011c2015-11-09 06:35:12 -08001241 };
1242 SkString noiseOctavesFuncName;
1243 SkString noiseOctavesCode;
1244 noiseOctavesCode.append("float result = 0.0;");
1245 noiseOctavesCode.append("float ratio = 1.0;");
1246 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1247 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1248 noiseOctavesCode.append("p *= 2.0;");
1249 noiseOctavesCode.append("ratio *= 2.0;");
1250 noiseOctavesCode.append("}");
1251 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
Herb Derby99d47212017-01-31 15:30:44 -05001252 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
ethannicholas417011c2015-11-09 06:35:12 -08001253 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1254
1255 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
Herb Derby99d47212017-01-31 15:30:44 -05001256 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
ethannicholas417011c2015-11-09 06:35:12 -08001257 zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001258 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001259 noiseOctavesFuncName.c_str(), zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001260 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001261 noiseOctavesFuncName.c_str(), zUni, octavesUni);
Herb Derby99d47212017-01-31 15:30:44 -05001262 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
ethannicholas417011c2015-11-09 06:35:12 -08001263 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1264 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1265
1266 // Clamp values
1267 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1268
1269 // Pre-multiply the result
1270 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1271 args.fOutputColor, args.fOutputColor,
1272 args.fOutputColor, args.fOutputColor);
1273}
1274
Brian Salomon94efbf52016-11-29 13:43:05 -05001275void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
ethannicholas417011c2015-11-09 06:35:12 -08001276 GrProcessorKeyBuilder* b) {
1277}
1278
1279void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1280 const GrProcessor& processor) {
1281 INHERITED::onSetData(pdman, processor);
1282
1283 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1284
1285 const SkVector& baseFrequency = noise.baseFrequency();
1286 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1287
egdaniel478c04e2015-11-09 07:40:49 -08001288 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
ethannicholas417011c2015-11-09 06:35:12 -08001289
1290 pdman.set1f(fZUni, noise.z());
1291}
1292
1293/////////////////////////////////////////////////////////////////////
brianosman839345d2016-07-22 11:04:53 -07001294sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1295 SkASSERT(args.fContext);
ethannicholas417011c2015-11-09 06:35:12 -08001296
1297 SkMatrix localMatrix = this->getLocalMatrix();
brianosman839345d2016-07-22 11:04:53 -07001298 if (args.fLocalMatrix) {
1299 localMatrix.preConcat(*args.fLocalMatrix);
ethannicholas417011c2015-11-09 06:35:12 -08001300 }
1301
brianosman839345d2016-07-22 11:04:53 -07001302 SkMatrix matrix = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001303 matrix.preConcat(localMatrix);
1304
1305 // Either we don't stitch tiles, either we have a valid tile size
1306 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1307
1308 SkPerlinNoiseShader2::PaintingData* paintingData =
1309 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1310
brianosman839345d2016-07-22 11:04:53 -07001311 SkMatrix m = *args.fViewMatrix;
ethannicholas417011c2015-11-09 06:35:12 -08001312 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1313 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1314
1315 if (fType == kImprovedNoise_Type) {
Brian Salomon514baff2016-11-17 15:17:07 -05001316 GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1317 GrSamplerParams::FilterMode::kNone_FilterMode);
Robert Phillipsbbd7a3b2017-03-21 08:48:40 -04001318 sk_sp<GrTextureProxy> permutationsTexture(
1319 GrRefCachedBitmapTextureProxy(args.fContext,
1320 paintingData->getImprovedPermutationsBitmap(),
1321 textureParams, nullptr));
1322 sk_sp<GrTextureProxy> gradientTexture(
1323 GrRefCachedBitmapTextureProxy(args.fContext,
1324 paintingData->getGradientBitmap(),
1325 textureParams, nullptr));
1326 return GrImprovedPerlinNoiseEffect::Make(args.fContext->resourceProvider(),
1327 fNumOctaves, fSeed, paintingData,
1328 std::move(permutationsTexture),
1329 std::move(gradientTexture), m);
ethannicholas417011c2015-11-09 06:35:12 -08001330 }
1331
1332 if (0 == fNumOctaves) {
1333 if (kFractalNoise_Type == fType) {
1334 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
Brian Osman618d3042016-10-25 10:51:28 -04001335 // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1336 // color space of the noise. Either way, this case (and the GLSL) need to convert to
1337 // the destination.
bungeman06ca8ec2016-06-09 08:01:03 -07001338 sk_sp<GrFragmentProcessor> inner(
Brian Osman618d3042016-10-25 10:51:28 -04001339 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
bungeman06ca8ec2016-06-09 08:01:03 -07001340 GrConstColorProcessor::kModulateRGBA_InputMode));
1341 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001342 }
1343 // Emit zero.
Brian Osman618d3042016-10-25 10:51:28 -04001344 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
1345 GrConstColorProcessor::kIgnore_InputMode);
ethannicholas417011c2015-11-09 06:35:12 -08001346 }
1347
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001348 sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy(
Robert Phillips26c90e02017-03-14 14:39:29 -04001349 args.fContext->resourceProvider(),
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001350 paintingData->getPermutationsBitmap());
Robert Phillips26c90e02017-03-14 14:39:29 -04001351 sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(args.fContext->resourceProvider(),
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001352 paintingData->getNoiseBitmap());
ethannicholas417011c2015-11-09 06:35:12 -08001353
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001354 if (permutationsProxy && noiseProxy) {
bungeman06ca8ec2016-06-09 08:01:03 -07001355 sk_sp<GrFragmentProcessor> inner(
Brian Osman32342f02017-03-04 08:12:46 -05001356 GrPerlinNoise2Effect::Make(args.fContext->resourceProvider(),
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001357 fType,
bungeman06ca8ec2016-06-09 08:01:03 -07001358 fNumOctaves,
1359 fStitchTiles,
1360 paintingData,
Robert Phillips6f9f7eb2017-02-18 15:15:51 -05001361 std::move(permutationsProxy),
1362 std::move(noiseProxy),
bungeman06ca8ec2016-06-09 08:01:03 -07001363 m));
1364 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
ethannicholas417011c2015-11-09 06:35:12 -08001365 }
1366 delete paintingData;
1367 return nullptr;
1368}
1369
1370#endif
1371
1372#ifndef SK_IGNORE_TO_STRING
1373void SkPerlinNoiseShader2::toString(SkString* str) const {
1374 str->append("SkPerlinNoiseShader2: (");
1375
1376 str->append("type: ");
1377 switch (fType) {
1378 case kFractalNoise_Type:
1379 str->append("\"fractal noise\"");
1380 break;
1381 case kTurbulence_Type:
1382 str->append("\"turbulence\"");
1383 break;
1384 default:
1385 str->append("\"unknown\"");
1386 break;
1387 }
1388 str->append(" base frequency: (");
1389 str->appendScalar(fBaseFrequencyX);
1390 str->append(", ");
1391 str->appendScalar(fBaseFrequencyY);
1392 str->append(") number of octaves: ");
1393 str->appendS32(fNumOctaves);
1394 str->append(" seed: ");
1395 str->appendScalar(fSeed);
1396 str->append(" stitch tiles: ");
1397 str->append(fStitchTiles ? "true " : "false ");
1398
1399 this->INHERITED::toString(str);
1400
1401 str->append(")");
1402}
1403#endif