2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkPerlinNoiseShader2.h"
10 #include "SkColorFilter.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
14 #include "SkUnPreMultiply.h"
18 #include "GrContext.h"
19 #include "GrCoordTransform.h"
20 #include "GrInvariantOutput.h"
22 #include "effects/GrConstColorProcessor.h"
23 #include "glsl/GrGLSLFragmentProcessor.h"
24 #include "glsl/GrGLSLFragmentShaderBuilder.h"
25 #include "glsl/GrGLSLProgramDataManager.h"
26 #include "glsl/GrGLSLUniformHandler.h"
29 static const int kBlockSize = 256;
30 static const int kBlockMask = kBlockSize - 1;
31 static const int kPerlinNoise = 4096;
32 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
34 static uint8_t improved_noise_permutations[] = {
35 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
36 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
37 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
38 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
39 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
40 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
41 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
42 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
43 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
44 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
45 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
46 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
47 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
48 141, 128, 195, 78, 66, 215, 61, 156, 180,
49 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103,
50 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26,
51 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174,
52 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231,
53 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143,
54 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
55 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124,
56 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17,
57 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101,
58 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185,
59 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81,
60 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176,
61 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
62 141, 128, 195, 78, 66, 215, 61, 156, 180
67 // noiseValue is the color component's value (or color)
68 // limitValue is the maximum perlin noise array index value allowed
69 // newValue is the current noise dimension (either width or height)
70 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
71 // If the noise value would bring us out of bounds of the current noise array while we are
72 // stiching noise tiles together, wrap the noise around the current dimension of the noise to
73 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
74 if (noiseValue >= limitValue) {
75 noiseValue -= newValue;
80 inline SkScalar smoothCurve(SkScalar t) {
81 static const SkScalar SK_Scalar3 = 3.0f;
83 // returns t * t * (3 - 2 * t)
84 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
89 struct SkPerlinNoiseShader2::StitchData {
97 bool operator==(const StitchData& other) const {
98 return fWidth == other.fWidth &&
99 fWrapX == other.fWrapX &&
100 fHeight == other.fHeight &&
101 fWrapY == other.fWrapY;
104 int fWidth; // How much to subtract to wrap for stitching.
105 int fWrapX; // Minimum value to wrap.
110 struct SkPerlinNoiseShader2::PaintingData {
111 PaintingData(const SkISize& tileSize, SkScalar seed,
112 SkScalar baseFrequencyX, SkScalar baseFrequencyY,
113 const SkMatrix& matrix)
116 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) },
117 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) },
119 matrix.mapVectors(vec, 2);
121 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY));
122 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY));
124 if (!fTileSize.isEmpty()) {
129 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
130 fPermutationsBitmap.setPixels(fLatticeSelector);
132 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
133 fNoiseBitmap.setPixels(fNoise[0][0]);
135 fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1));
136 fImprovedPermutationsBitmap.setPixels(improved_noise_permutations);
138 fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1));
139 static uint8_t gradients[] = { 2, 2, 1, 0,
155 fGradientBitmap.setPixels(gradients);
160 uint8_t fLatticeSelector[kBlockSize];
161 uint16_t fNoise[4][kBlockSize][2];
162 SkPoint fGradient[4][kBlockSize];
164 SkVector fBaseFrequency;
165 StitchData fStitchDataInit;
170 SkBitmap fPermutationsBitmap;
171 SkBitmap fNoiseBitmap;
172 SkBitmap fImprovedPermutationsBitmap;
173 SkBitmap fGradientBitmap;
176 inline int random() {
177 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
178 static const int gRandQ = 127773; // m / a
179 static const int gRandR = 2836; // m % a
181 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
183 result += kRandMaximum;
188 // Only called once. Could be part of the constructor.
189 void init(SkScalar seed)
191 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
193 // According to the SVG spec, we must truncate (not round) the seed value.
194 fSeed = SkScalarTruncToInt(seed);
195 // The seed value clamp to the range [1, kRandMaximum - 1].
197 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
199 if (fSeed > kRandMaximum - 1) {
200 fSeed = kRandMaximum - 1;
202 for (int channel = 0; channel < 4; ++channel) {
203 for (int i = 0; i < kBlockSize; ++i) {
204 fLatticeSelector[i] = i;
205 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
206 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
209 for (int i = kBlockSize - 1; i > 0; --i) {
210 int k = fLatticeSelector[i];
211 int j = random() % kBlockSize;
213 SkASSERT(j < kBlockSize);
214 fLatticeSelector[i] = fLatticeSelector[j];
215 fLatticeSelector[j] = k;
218 // Perform the permutations now
221 uint16_t noise[4][kBlockSize][2];
222 for (int i = 0; i < kBlockSize; ++i) {
223 for (int channel = 0; channel < 4; ++channel) {
224 for (int j = 0; j < 2; ++j) {
225 noise[channel][i][j] = fNoise[channel][i][j];
229 // Do permutations on noise data
230 for (int i = 0; i < kBlockSize; ++i) {
231 for (int channel = 0; channel < 4; ++channel) {
232 for (int j = 0; j < 2; ++j) {
233 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
239 // Half of the largest possible value for 16 bit unsigned int
240 static const SkScalar gHalfMax16bits = 32767.5f;
242 // Compute gradients from permutated noise data
243 for (int channel = 0; channel < 4; ++channel) {
244 for (int i = 0; i < kBlockSize; ++i) {
245 fGradient[channel][i] = SkPoint::Make(
246 SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
248 SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
250 fGradient[channel][i].normalize();
251 // Put the normalized gradient back into the noise data
252 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
253 fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
254 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
255 fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
260 // Only called once. Could be part of the constructor.
262 SkScalar tileWidth = SkIntToScalar(fTileSize.width());
263 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
264 SkASSERT(tileWidth > 0 && tileHeight > 0);
265 // When stitching tiled turbulence, the frequencies must be adjusted
266 // so that the tile borders will be continuous.
267 if (fBaseFrequency.fX) {
268 SkScalar lowFrequencx =
269 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
270 SkScalar highFrequencx =
271 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
272 // BaseFrequency should be non-negative according to the standard.
273 if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) {
274 fBaseFrequency.fX = lowFrequencx;
276 fBaseFrequency.fX = highFrequencx;
279 if (fBaseFrequency.fY) {
280 SkScalar lowFrequency =
281 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
282 SkScalar highFrequency =
283 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
284 if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) {
285 fBaseFrequency.fY = lowFrequency;
287 fBaseFrequency.fY = highFrequency;
290 // Set up TurbulenceInitial stitch values.
291 fStitchDataInit.fWidth =
292 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
293 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
294 fStitchDataInit.fHeight =
295 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
296 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
302 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
304 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
306 const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; }
308 const SkBitmap& getGradientBitmap() const { return fGradientBitmap; }
312 sk_sp<SkShader> SkPerlinNoiseShader2::MakeFractalNoise(SkScalar baseFrequencyX,
313 SkScalar baseFrequencyY,
314 int numOctaves, SkScalar seed,
315 const SkISize* tileSize) {
316 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX,
317 baseFrequencyY, numOctaves, seed, tileSize));
320 sk_sp<SkShader> SkPerlinNoiseShader2::MakeTurbulence(SkScalar baseFrequencyX,
321 SkScalar baseFrequencyY,
322 int numOctaves, SkScalar seed,
323 const SkISize* tileSize) {
324 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX,
325 baseFrequencyY, numOctaves, seed, tileSize));
328 sk_sp<SkShader> SkPerlinNoiseShader2::MakeImprovedNoise(SkScalar baseFrequencyX,
329 SkScalar baseFrequencyY,
330 int numOctaves, SkScalar z) {
331 return sk_sp<SkShader>(new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX,
332 baseFrequencyY, numOctaves, z, NULL));
335 SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type,
336 SkScalar baseFrequencyX,
337 SkScalar baseFrequencyY,
340 const SkISize* tileSize)
342 , fBaseFrequencyX(baseFrequencyX)
343 , fBaseFrequencyY(baseFrequencyY)
344 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
346 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize)
347 , fStitchTiles(!fTileSize.isEmpty())
349 SkASSERT(numOctaves >= 0 && numOctaves < 256);
352 SkPerlinNoiseShader2::~SkPerlinNoiseShader2() {
355 sk_sp<SkFlattenable> SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) {
356 Type type = (Type)buffer.readInt();
357 SkScalar freqX = buffer.readScalar();
358 SkScalar freqY = buffer.readScalar();
359 int octaves = buffer.readInt();
360 SkScalar seed = buffer.readScalar();
362 tileSize.fWidth = buffer.readInt();
363 tileSize.fHeight = buffer.readInt();
366 case kFractalNoise_Type:
367 return SkPerlinNoiseShader2::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize);
368 case kTurbulence_Type:
369 return SkPerlinNoiseShader2::MakeTubulence(freqX, freqY, octaves, seed, &tileSize);
370 case kImprovedNoise_Type:
371 return SkPerlinNoiseShader2::MakeImprovedNoise(freqX, freqY, octaves, seed);
377 void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const {
378 buffer.writeInt((int) fType);
379 buffer.writeScalar(fBaseFrequencyX);
380 buffer.writeScalar(fBaseFrequencyY);
381 buffer.writeInt(fNumOctaves);
382 buffer.writeScalar(fSeed);
383 buffer.writeInt(fTileSize.fWidth);
384 buffer.writeInt(fTileSize.fHeight);
387 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D(
388 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
390 int noisePositionIntegerValue;
391 int nextNoisePositionIntegerValue;
392 SkScalar noisePositionFractionValue;
393 Noise(SkScalar component)
395 SkScalar position = component + kPerlinNoise;
396 noisePositionIntegerValue = SkScalarFloorToInt(position);
397 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
398 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
401 Noise noiseX(noiseVector.x());
402 Noise noiseY(noiseVector.y());
404 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
405 // If stitching, adjust lattice points accordingly.
406 if (perlinNoiseShader.fStitchTiles) {
407 noiseX.noisePositionIntegerValue =
408 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
409 noiseY.noisePositionIntegerValue =
410 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
411 noiseX.nextNoisePositionIntegerValue =
412 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
413 noiseY.nextNoisePositionIntegerValue =
414 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
416 noiseX.noisePositionIntegerValue &= kBlockMask;
417 noiseY.noisePositionIntegerValue &= kBlockMask;
418 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
419 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
421 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
423 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
424 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
425 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
426 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
427 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
428 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
429 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
430 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
431 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
432 noiseY.noisePositionFractionValue); // Offset (0,0)
433 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
434 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
435 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
436 SkScalar a = SkScalarInterp(u, v, sx);
437 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
438 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
439 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
440 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
441 SkScalar b = SkScalarInterp(u, v, sx);
442 return SkScalarInterp(a, b, sy);
445 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
446 int channel, StitchData& stitchData, const SkPoint& point) const {
447 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
448 if (perlinNoiseShader.fStitchTiles) {
449 // Set up TurbulenceInitial stitch values.
450 stitchData = fPaintingData->fStitchDataInit;
452 SkScalar turbulenceFunctionResult = 0;
453 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
454 SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
455 SkScalar ratio = SK_Scalar1;
456 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
457 SkScalar noise = noise2D(channel, stitchData, noiseVector);
458 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ?
459 noise : SkScalarAbs(noise);
460 turbulenceFunctionResult += numer / ratio;
464 if (perlinNoiseShader.fStitchTiles) {
465 // Update stitch values
466 stitchData.fWidth *= 2;
467 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
468 stitchData.fHeight *= 2;
469 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
473 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
474 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
475 if (perlinNoiseShader.fType == kFractalNoise_Type) {
476 turbulenceFunctionResult =
477 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
480 if (channel == 3) { // Scale alpha by paint value
481 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255;
485 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
488 ////////////////////////////////////////////////////////////////////////////////////////////////////
489 // Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/
490 static SkScalar fade(SkScalar t) {
491 return t * t * t * (t * (t * 6 - 15) + 10);
494 static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) {
495 return a + t * (b - a);
498 static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) {
500 SkScalar u = h < 8 ? x : y;
501 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z;
502 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
505 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint(
506 int channel, const SkPoint& point) const {
507 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
508 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX;
509 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY;
510 // z offset between different channels, chosen arbitrarily
511 static const SkScalar CHANNEL_DELTA = 1000.0f;
512 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed;
514 SkScalar ratio = SK_Scalar1;
515 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) {
516 int X = SkScalarFloorToInt(x) & 255;
517 int Y = SkScalarFloorToInt(y) & 255;
518 int Z = SkScalarFloorToInt(z) & 255;
519 SkScalar px = x - SkScalarFloorToScalar(x);
520 SkScalar py = y - SkScalarFloorToScalar(y);
521 SkScalar pz = z - SkScalarFloorToScalar(z);
522 SkScalar u = fade(px);
523 SkScalar v = fade(py);
524 SkScalar w = fade(pz);
525 uint8_t* permutations = improved_noise_permutations;
526 int A = permutations[X] + Y;
527 int AA = permutations[A] + Z;
528 int AB = permutations[A + 1] + Z;
529 int B = permutations[X + 1] + Y;
530 int BA = permutations[B] + Z;
531 int BB = permutations[B + 1] + Z;
532 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ),
533 grad(permutations[BA ], px - 1, py , pz )),
534 lerp(u, grad(permutations[AB ], px , py - 1, pz ),
535 grad(permutations[BB ], px - 1, py - 1, pz ))),
536 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1),
537 grad(permutations[BA + 1], px - 1, py , pz - 1)),
538 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1),
539 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) /
545 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f);
548 ////////////////////////////////////////////////////////////////////////////////////////////////////
550 SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade(
551 const SkPoint& point, StitchData& stitchData) const {
552 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNoiseShader2&>(fShader);
554 fMatrix.mapPoints(&newPoint, &point, 1);
555 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
556 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
559 for (int channel = 3; channel >= 0; --channel) {
561 if (perlinNoiseShader.fType == kImprovedNoise_Type) {
562 value = calculateImprovedNoiseValueForPoint(channel, newPoint);
565 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint);
567 rgba[channel] = SkScalarFloorToInt(255 * value);
569 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
572 SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec,
573 void* storage) const {
574 return new (storage) PerlinNoiseShaderContext(*this, rec);
577 size_t SkPerlinNoiseShader2::onContextSize(const ContextRec&) const {
578 return sizeof(PerlinNoiseShaderContext);
581 SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
582 const SkPerlinNoiseShader2& shader, const ContextRec& rec)
583 : INHERITED(shader, rec)
585 SkMatrix newMatrix = *rec.fMatrix;
586 newMatrix.preConcat(shader.getLocalMatrix());
587 if (rec.fLocalMatrix) {
588 newMatrix.preConcat(*rec.fLocalMatrix);
590 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
591 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
592 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
593 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX,
594 shader.fBaseFrequencyY, newMatrix);
597 SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; }
599 void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan(
600 int x, int y, SkPMColor result[], int count) {
601 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
602 StitchData stitchData;
603 for (int i = 0; i < count; ++i) {
604 result[i] = shade(point, stitchData);
605 point.fX += SK_Scalar1;
609 /////////////////////////////////////////////////////////////////////
613 class GrGLPerlinNoise2 : public GrGLSLFragmentProcessor {
615 void emitCode(EmitArgs&) override;
617 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
620 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
623 GrGLSLProgramDataManager::UniformHandle fStitchDataUni;
624 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
626 typedef GrGLSLFragmentProcessor INHERITED;
629 /////////////////////////////////////////////////////////////////////
631 class GrPerlinNoise2Effect : public GrFragmentProcessor {
633 static sk_sp<GrFragmentProcessor> Make(SkPerlinNoiseShader2::Type type,
634 int numOctaves, bool stitchTiles,
635 SkPerlinNoiseShader2::PaintingData* paintingData,
636 GrTexture* permutationsTexture, GrTexture* noiseTexture,
637 const SkMatrix& matrix) {
638 return sk_sp<GrFragmentProcessor>(
639 new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingData,
640 permutationsTexture, noiseTexture, matrix));
643 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; }
645 const char* name() const override { return "PerlinNoise"; }
647 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
649 SkPerlinNoiseShader2::Type type() const { return fType; }
650 bool stitchTiles() const { return fStitchTiles; }
651 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
652 int numOctaves() const { return fNumOctaves; }
653 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
656 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
657 return new GrGLPerlinNoise2;
660 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
661 GrProcessorKeyBuilder* b) const override {
662 GrGLPerlinNoise2::GenKey(*this, caps, b);
665 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
666 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>();
667 return fType == s.fType &&
668 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
669 fNumOctaves == s.fNumOctaves &&
670 fStitchTiles == s.fStitchTiles &&
671 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
674 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
675 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
678 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type,
679 int numOctaves, bool stitchTiles,
680 SkPerlinNoiseShader2::PaintingData* paintingData,
681 GrTexture* permutationsTexture, GrTexture* noiseTexture,
682 const SkMatrix& matrix)
684 , fNumOctaves(numOctaves)
685 , fStitchTiles(stitchTiles)
686 , fPermutationsSampler(permutationsTexture)
687 , fNoiseSampler(noiseTexture)
688 , fPaintingData(paintingData) {
689 this->initClassID<GrPerlinNoise2Effect>();
690 this->addTextureSampler(&fPermutationsSampler);
691 this->addTextureSampler(&fNoiseSampler);
692 fCoordTransform.reset(matrix);
693 this->addCoordTransform(&fCoordTransform);
696 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
698 SkPerlinNoiseShader2::Type fType;
699 GrCoordTransform fCoordTransform;
702 TextureSampler fPermutationsSampler;
703 TextureSampler fNoiseSampler;
704 SkPerlinNoiseShader2::PaintingData* fPaintingData;
707 typedef GrFragmentProcessor INHERITED;
710 /////////////////////////////////////////////////////////////////////
711 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect);
713 sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) {
714 int numOctaves = d->fRandom->nextRangeU(2, 10);
715 bool stitchTiles = d->fRandom->nextBool();
716 SkScalar seed = SkIntToScalar(d->fRandom->nextU());
717 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096),
718 d->fRandom->nextRangeU(4, 4096));
719 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
721 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
724 sk_sp<SkShader> shader(d->fRandom->nextBool() ?
725 SkPerlinNoiseShader2::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
726 stitchTiles ? &tileSize : nullptr) :
727 SkPerlinNoiseShader2::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
728 stitchTiles ? &tileSize : nullptr));
730 GrTest::TestAsFPArgs asFPArgs(d);
731 return shader->asFragmentProcessor(asFPArgs.args());
734 void GrGLPerlinNoise2::emitCode(EmitArgs& args) {
735 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>();
737 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
738 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
739 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
741 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
742 kVec2f_GrSLType, kDefault_GrSLPrecision,
744 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
746 const char* stitchDataUni = nullptr;
747 if (pne.stitchTiles()) {
748 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
749 kVec2f_GrSLType, kDefault_GrSLPrecision,
751 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni);
754 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
755 const char* chanCoordR = "0.125";
756 const char* chanCoordG = "0.375";
757 const char* chanCoordB = "0.625";
758 const char* chanCoordA = "0.875";
759 const char* chanCoord = "chanCoord";
760 const char* stitchData = "stitchData";
761 const char* ratio = "ratio";
762 const char* noiseVec = "noiseVec";
763 const char* noiseSmooth = "noiseSmooth";
764 const char* floorVal = "floorVal";
765 const char* fractVal = "fractVal";
766 const char* uv = "uv";
767 const char* ab = "ab";
768 const char* latticeIdx = "latticeIdx";
769 const char* bcoords = "bcoords";
770 const char* lattice = "lattice";
771 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
772 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
773 // [-1,1] vector and perform a dot product between that vector and the provided vector.
774 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
776 // Add noise function
777 static const GrShaderVar gPerlinNoiseArgs[] = {
778 GrShaderVar(chanCoord, kFloat_GrSLType),
779 GrShaderVar(noiseVec, kVec2f_GrSLType)
782 static const GrShaderVar gPerlinNoiseStitchArgs[] = {
783 GrShaderVar(chanCoord, kFloat_GrSLType),
784 GrShaderVar(noiseVec, kVec2f_GrSLType),
785 GrShaderVar(stitchData, kVec2f_GrSLType)
790 noiseCode.appendf("\tvec4 %s;\n", floorVal);
791 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
792 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
793 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
795 // smooth curve : t * t * (3 - 2 * t)
796 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
797 noiseSmooth, fractVal, fractVal, fractVal);
799 // Adjust frequencies if we're stitching tiles
800 if (pne.stitchTiles()) {
801 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
802 floorVal, stitchData, floorVal, stitchData);
803 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
804 floorVal, stitchData, floorVal, stitchData);
805 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
806 floorVal, stitchData, floorVal, stitchData);
807 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
808 floorVal, stitchData, floorVal, stitchData);
811 // Get texture coordinates and normalize
812 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
815 // Get permutation for x
817 SkString xCoords("");
818 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
820 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
821 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
823 noiseCode.append(".r;");
826 // Get permutation for x + 1
828 SkString xCoords("");
829 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
831 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
832 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(),
834 noiseCode.append(".r;");
837 #if defined(SK_BUILD_FOR_ANDROID)
838 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
839 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
840 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
841 // (or 0.484368 here). The following rounding operation prevents these precision issues from
842 // affecting the result of the noise by making sure that we only have multiples of 1/255.
843 // (Note that 1/255 is about 0.003921569, which is the value used here).
844 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
845 latticeIdx, latticeIdx);
848 // Get (x,y) coordinates with the permutated x
849 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
851 noiseCode.appendf("\n\n\tvec2 %s;", uv);
852 // Compute u, at offset (0,0)
854 SkString latticeCoords("");
855 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
856 noiseCode.appendf("\n\tvec4 %s = ", lattice);
857 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
859 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
860 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
863 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
864 // Compute v, at offset (-1,0)
866 SkString latticeCoords("");
867 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
868 noiseCode.append("\n\tlattice = ");
869 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
871 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
872 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
875 // Compute 'a' as a linear interpolation of 'u' and 'v'
876 noiseCode.appendf("\n\tvec2 %s;", ab);
877 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
879 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
880 // Compute v, at offset (-1,-1)
882 SkString latticeCoords("");
883 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
884 noiseCode.append("\n\tlattice = ");
885 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
887 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
888 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
891 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
892 // Compute u, at offset (0,-1)
894 SkString latticeCoords("");
895 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
896 noiseCode.append("\n\tlattice = ");
897 fsBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(),
899 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
900 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
903 // Compute 'b' as a linear interpolation of 'u' and 'v'
904 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
905 // Compute the noise as a linear interpolation of 'a' and 'b'
906 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
908 SkString noiseFuncName;
909 if (pne.stitchTiles()) {
910 fsBuilder->emitFunction(kFloat_GrSLType,
911 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
912 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
914 fsBuilder->emitFunction(kFloat_GrSLType,
915 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
916 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
919 // There are rounding errors if the floor operation is not performed here
920 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
921 noiseVec, vCoords.c_str(), baseFrequencyUni);
923 // Clear the color accumulator
924 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor);
926 if (pne.stitchTiles()) {
927 // Set up TurbulenceInitial stitch values.
928 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
931 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
933 // Loop over all octaves
934 fsBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves());
936 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor);
937 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
938 fsBuilder->codeAppend("abs(");
940 if (pne.stitchTiles()) {
941 fsBuilder->codeAppendf(
942 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
943 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
944 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
945 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
946 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
947 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
949 fsBuilder->codeAppendf(
950 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
951 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
952 noiseFuncName.c_str(), chanCoordR, noiseVec,
953 noiseFuncName.c_str(), chanCoordG, noiseVec,
954 noiseFuncName.c_str(), chanCoordB, noiseVec,
955 noiseFuncName.c_str(), chanCoordA, noiseVec);
957 if (pne.type() != SkPerlinNoiseShader2::kFractalNoise_Type) {
958 fsBuilder->codeAppendf(")"); // end of "abs("
960 fsBuilder->codeAppendf(" * %s;", ratio);
962 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
963 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
965 if (pne.stitchTiles()) {
966 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
968 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
970 if (pne.type() == SkPerlinNoiseShader2::kFractalNoise_Type) {
971 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
972 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
973 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);",
974 args.fOutputColor,args.fOutputColor);
978 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
980 // Pre-multiply the result
981 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
982 args.fOutputColor, args.fOutputColor,
983 args.fOutputColor, args.fOutputColor);
986 void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrShaderCaps&,
987 GrProcessorKeyBuilder* b) {
988 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
990 uint32_t key = turbulence.numOctaves();
992 key = key << 3; // Make room for next 3 bits
994 switch (turbulence.type()) {
995 case SkPerlinNoiseShader2::kFractalNoise_Type:
998 case SkPerlinNoiseShader2::kTurbulence_Type:
1006 if (turbulence.stitchTiles()) {
1007 key |= 0x4; // Flip the 3rd bit if tile stitching is on
1013 void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman,
1014 const GrProcessor& processor) {
1015 INHERITED::onSetData(pdman, processor);
1017 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>();
1019 const SkVector& baseFrequency = turbulence.baseFrequency();
1020 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1022 if (turbulence.stitchTiles()) {
1023 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchData();
1024 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
1025 SkIntToScalar(stitchData.fHeight));
1029 /////////////////////////////////////////////////////////////////////
1031 class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor {
1033 void emitCode(EmitArgs&) override;
1035 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
1038 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1041 GrGLSLProgramDataManager::UniformHandle fZUni;
1042 GrGLSLProgramDataManager::UniformHandle fOctavesUni;
1043 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni;
1045 typedef GrGLSLFragmentProcessor INHERITED;
1048 /////////////////////////////////////////////////////////////////////
1050 class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor {
1052 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z,
1053 SkPerlinNoiseShader2::PaintingData* paintingData,
1054 GrTexture* permutationsTexture,
1055 GrTexture* gradientTexture,
1056 const SkMatrix& matrix) {
1057 return sk_sp<GrFragmentProcessor>(
1058 new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permutationsTexture,
1059 gradientTexture, matrix));
1062 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; }
1064 const char* name() const override { return "ImprovedPerlinNoise"; }
1066 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
1067 SkScalar z() const { return fZ; }
1068 int octaves() const { return fOctaves; }
1069 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
1072 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
1073 return new GrGLImprovedPerlinNoise;
1076 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
1077 GrGLImprovedPerlinNoise::GenKey(*this, caps, b);
1080 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
1081 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>();
1083 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency;
1086 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
1087 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
1090 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z,
1091 SkPerlinNoiseShader2::PaintingData* paintingData,
1092 GrTexture* permutationsTexture, GrTexture* gradientTexture,
1093 const SkMatrix& matrix)
1096 , fPermutationsSampler(permutationsTexture)
1097 , fGradientSampler(gradientTexture)
1098 , fPaintingData(paintingData) {
1099 this->initClassID<GrImprovedPerlinNoiseEffect>();
1100 this->addTextureSampler(&fPermutationsSampler);
1101 this->addTextureSampler(&fGradientSampler);
1102 fCoordTransform.reset(matrix);
1103 this->addCoordTransform(&fCoordTransform);
1106 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
1108 GrCoordTransform fCoordTransform;
1111 TextureSampler fPermutationsSampler;
1112 TextureSampler fGradientSampler;
1113 SkPerlinNoiseShader2::PaintingData* fPaintingData;
1116 typedef GrFragmentProcessor INHERITED;
1119 /////////////////////////////////////////////////////////////////////
1120 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect);
1122 sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) {
1123 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f,
1125 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f,
1127 int numOctaves = d->fRandom->nextRangeU(2, 10);
1128 SkScalar z = SkIntToScalar(d->fRandom->nextU());
1130 sk_sp<SkShader> shader(SkPerlinNoiseShader2::MakeImprovedNoise(baseFrequencyX,
1135 GrTest::TestAsFPArgs asFPArgs(d);
1136 return shader->asFragmentProcessor(asFPArgs.args());
1139 void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) {
1140 GrGLSLFragmentBuilder* fsBuilder = args.fFragBuilder;
1141 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1142 SkString vCoords = fsBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1144 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1145 kVec2f_GrSLType, kDefault_GrSLPrecision,
1147 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni);
1149 fOctavesUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1150 kFloat_GrSLType, kDefault_GrSLPrecision,
1152 const char* octavesUni = uniformHandler->getUniformCStr(fOctavesUni);
1154 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1155 kFloat_GrSLType, kDefault_GrSLPrecision,
1157 const char* zUni = uniformHandler->getUniformCStr(fZUni);
1160 static const GrShaderVar fadeArgs[] = {
1161 GrShaderVar("t", kVec3f_GrSLType)
1163 SkString fadeFuncName;
1164 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs),
1166 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
1170 static const GrShaderVar permArgs[] = {
1171 GrShaderVar("x", kFloat_GrSLType)
1173 SkString permFuncName;
1174 SkString permCode("return ");
1175 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not
1176 // sure why. Using fract() (here and the next texture lookup) as a workaround.
1177 fsBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)",
1179 permCode.append(".r * 255.0;");
1180 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs,
1181 permCode.c_str(), &permFuncName);
1184 static const GrShaderVar gradArgs[] = {
1185 GrShaderVar("x", kFloat_GrSLType),
1186 GrShaderVar("p", kVec3f_GrSLType)
1188 SkString gradFuncName;
1189 SkString gradCode("return dot(");
1190 fsBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)",
1192 gradCode.append(".rgb * 255.0 - vec3(1.0), p);");
1193 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs,
1194 gradCode.c_str(), &gradFuncName);
1197 static const GrShaderVar lerpArgs[] = {
1198 GrShaderVar("a", kFloat_GrSLType),
1199 GrShaderVar("b", kFloat_GrSLType),
1200 GrShaderVar("w", kFloat_GrSLType)
1202 SkString lerpFuncName;
1203 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs,
1204 "return a + w * (b - a);", &lerpFuncName);
1207 static const GrShaderVar noiseArgs[] = {
1208 GrShaderVar("p", kVec3f_GrSLType),
1210 SkString noiseFuncName;
1212 noiseCode.append("vec3 P = mod(floor(p), 256.0);");
1213 noiseCode.append("p -= floor(p);");
1214 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str());
1215 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str());
1216 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str());
1217 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str());
1218 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str());
1219 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str());
1220 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str());
1221 noiseCode.appendf("float result = %s(", lerpFuncName.c_str());
1222 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(),
1223 gradFuncName.c_str(), permFuncName.c_str());
1224 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(),
1225 permFuncName.c_str());
1226 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(),
1227 gradFuncName.c_str(), permFuncName.c_str());
1228 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),",
1229 gradFuncName.c_str(), permFuncName.c_str());
1230 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),",
1231 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(),
1232 permFuncName.c_str());
1233 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),",
1234 gradFuncName.c_str(), permFuncName.c_str());
1235 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),",
1236 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str());
1237 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);",
1238 gradFuncName.c_str(), permFuncName.c_str());
1239 noiseCode.append("return result;");
1240 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs,
1241 noiseCode.c_str(), &noiseFuncName);
1243 // noiseOctaves function
1244 static const GrShaderVar noiseOctavesArgs[] = {
1245 GrShaderVar("p", kVec3f_GrSLType),
1246 GrShaderVar("octaves", kFloat_GrSLType),
1248 SkString noiseOctavesFuncName;
1249 SkString noiseOctavesCode;
1250 noiseOctavesCode.append("float result = 0.0;");
1251 noiseOctavesCode.append("float ratio = 1.0;");
1252 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {");
1253 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str());
1254 noiseOctavesCode.append("p *= 2.0;");
1255 noiseOctavesCode.append("ratio *= 2.0;");
1256 noiseOctavesCode.append("}");
1257 noiseOctavesCode.append("return (result + 1.0) / 2.0;");
1258 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs),
1259 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName);
1261 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni);
1262 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFuncName.c_str(),
1264 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0), %s);",
1265 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1266 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0), %s);",
1267 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1268 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0), %s);",
1269 noiseOctavesFuncName.c_str(), zUni, octavesUni);
1270 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor);
1273 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor);
1275 // Pre-multiply the result
1276 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
1277 args.fOutputColor, args.fOutputColor,
1278 args.fOutputColor, args.fOutputColor);
1281 void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&,
1282 GrProcessorKeyBuilder* b) {
1285 void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman,
1286 const GrProcessor& processor) {
1287 INHERITED::onSetData(pdman, processor);
1289 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>();
1291 const SkVector& baseFrequency = noise.baseFrequency();
1292 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
1294 pdman.set1f(fOctavesUni, SkIntToScalar(noise.octaves()));
1296 pdman.set1f(fZUni, noise.z());
1299 /////////////////////////////////////////////////////////////////////
1300 sk_sp<GrFragmentProcessor> SkPerlinNoiseShader2::asFragmentProcessor(const AsFPArgs& args) const {
1301 SkASSERT(args.fContext);
1303 SkMatrix localMatrix = this->getLocalMatrix();
1304 if (args.fLocalMatrix) {
1305 localMatrix.preConcat(*args.fLocalMatrix);
1308 SkMatrix matrix = *args.fViewMatrix;
1309 matrix.preConcat(localMatrix);
1311 // Either we don't stitch tiles, either we have a valid tile size
1312 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
1314 SkPerlinNoiseShader2::PaintingData* paintingData =
1315 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix);
1317 SkMatrix m = *args.fViewMatrix;
1318 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1319 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1321 if (fType == kImprovedNoise_Type) {
1322 GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode,
1323 GrSamplerParams::FilterMode::kNone_FilterMode);
1324 sk_sp<GrTexture> permutationsTexture(
1325 GrRefCachedBitmapTexture(args.fContext, paintingData->getImprovedPermutationsBitmap(),
1327 sk_sp<GrTexture> gradientTexture(
1328 GrRefCachedBitmapTexture(args.fContext, paintingData->getGradientBitmap(),
1330 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, paintingData,
1331 permutationsTexture.get(),
1332 gradientTexture.get(), m);
1335 if (0 == fNumOctaves) {
1336 if (kFractalNoise_Type == fType) {
1337 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2)
1338 // TODO: Either treat the output of this shader as sRGB or allow client to specify a
1339 // color space of the noise. Either way, this case (and the GLSL) need to convert to
1341 sk_sp<GrFragmentProcessor> inner(
1342 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040),
1343 GrConstColorProcessor::kModulateRGBA_InputMode));
1344 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
1347 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(),
1348 GrConstColorProcessor::kIgnore_InputMode);
1351 sk_sp<GrTexture> permutationsTexture(
1352 GrRefCachedBitmapTexture(args.fContext, paintingData->getPermutationsBitmap(),
1353 GrSamplerParams::ClampNoFilter()));
1354 sk_sp<GrTexture> noiseTexture(
1355 GrRefCachedBitmapTexture(args.fContext, paintingData->getNoiseBitmap(),
1356 GrSamplerParams::ClampNoFilter()));
1358 if ((permutationsTexture) && (noiseTexture)) {
1359 sk_sp<GrFragmentProcessor> inner(
1360 GrPerlinNoise2Effect::Make(fType,
1364 permutationsTexture.get(), noiseTexture.get(),
1366 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner));
1368 delete paintingData;
1374 #ifndef SK_IGNORE_TO_STRING
1375 void SkPerlinNoiseShader2::toString(SkString* str) const {
1376 str->append("SkPerlinNoiseShader2: (");
1378 str->append("type: ");
1380 case kFractalNoise_Type:
1381 str->append("\"fractal noise\"");
1383 case kTurbulence_Type:
1384 str->append("\"turbulence\"");
1387 str->append("\"unknown\"");
1390 str->append(" base frequency: (");
1391 str->appendScalar(fBaseFrequencyX);
1393 str->appendScalar(fBaseFrequencyY);
1394 str->append(") number of octaves: ");
1395 str->appendS32(fNumOctaves);
1396 str->append(" seed: ");
1397 str->appendScalar(fSeed);
1398 str->append(" stitch tiles: ");
1399 str->append(fStitchTiles ? "true " : "false ");
1401 this->INHERITED::toString(str);