SkPerlinNoiseShader.cpp revision c352f3b89a28fd06bf9b124bfc960d9581949716
1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkPerlinNoiseShader.h" 9 10#include "SkArenaAlloc.h" 11#include "SkDither.h" 12#include "SkColorFilter.h" 13#include "SkMakeUnique.h" 14#include "SkReadBuffer.h" 15#include "SkWriteBuffer.h" 16#include "SkShader.h" 17#include "SkUnPreMultiply.h" 18#include "SkString.h" 19 20#if SK_SUPPORT_GPU 21#include "GrContext.h" 22#include "GrCoordTransform.h" 23#include "SkGr.h" 24#include "effects/GrConstColorProcessor.h" 25#include "glsl/GrGLSLFragmentProcessor.h" 26#include "glsl/GrGLSLFragmentShaderBuilder.h" 27#include "glsl/GrGLSLProgramDataManager.h" 28#include "glsl/GrGLSLUniformHandler.h" 29#endif 30 31static const int kBlockSize = 256; 32static const int kBlockMask = kBlockSize - 1; 33static const int kPerlinNoise = 4096; 34static const int kRandMaximum = SK_MaxS32; // 2**31 - 1 35 36static uint8_t improved_noise_permutations[] = { 37 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 38 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 39 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 40 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 41 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 42 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 43 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 44 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 45 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 46 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 47 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 48 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 49 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 50 141, 128, 195, 78, 66, 215, 61, 156, 180, 51 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 52 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 53 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 54 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 55 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 56 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 57 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 58 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 59 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 60 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 61 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 62 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 63 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 64 141, 128, 195, 78, 66, 215, 61, 156, 180 65}; 66 67class SkPerlinNoiseShaderImpl : public SkShaderBase { 68public: 69 struct StitchData { 70 StitchData() 71 : fWidth(0) 72 , fWrapX(0) 73 , fHeight(0) 74 , fWrapY(0) 75 {} 76 77 bool operator==(const StitchData& other) const { 78 return fWidth == other.fWidth && 79 fWrapX == other.fWrapX && 80 fHeight == other.fHeight && 81 fWrapY == other.fWrapY; 82 } 83 84 int fWidth; // How much to subtract to wrap for stitching. 85 int fWrapX; // Minimum value to wrap. 86 int fHeight; 87 int fWrapY; 88 }; 89 90 struct PaintingData { 91 PaintingData(const SkISize& tileSize, SkScalar seed, 92 SkScalar baseFrequencyX, SkScalar baseFrequencyY, 93 const SkMatrix& matrix) 94 { 95 SkVector vec[2] = { 96 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) }, 97 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) }, 98 }; 99 matrix.mapVectors(vec, 2); 100 101 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY)); 102 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY)); 103 this->init(seed); 104 if (!fTileSize.isEmpty()) { 105 this->stitch(); 106 } 107 108 #if SK_SUPPORT_GPU 109 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); 110 fPermutationsBitmap.setPixels(fLatticeSelector); 111 112 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); 113 fNoiseBitmap.setPixels(fNoise[0][0]); 114 115 fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1)); 116 fImprovedPermutationsBitmap.setPixels(improved_noise_permutations); 117 118 fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1)); 119 static uint8_t gradients[] = { 2, 2, 1, 0, 120 0, 2, 1, 0, 121 2, 0, 1, 0, 122 0, 0, 1, 0, 123 2, 1, 2, 0, 124 0, 1, 2, 0, 125 2, 1, 0, 0, 126 0, 1, 0, 0, 127 1, 2, 2, 0, 128 1, 0, 2, 0, 129 1, 2, 0, 0, 130 1, 0, 0, 0, 131 2, 2, 1, 0, 132 1, 0, 2, 0, 133 0, 2, 1, 0, 134 1, 0, 0, 0 }; 135 fGradientBitmap.setPixels(gradients); 136 #endif 137 } 138 139 int fSeed; 140 uint8_t fLatticeSelector[kBlockSize]; 141 uint16_t fNoise[4][kBlockSize][2]; 142 SkPoint fGradient[4][kBlockSize]; 143 SkISize fTileSize; 144 SkVector fBaseFrequency; 145 StitchData fStitchDataInit; 146 147 private: 148 149 #if SK_SUPPORT_GPU 150 SkBitmap fPermutationsBitmap; 151 SkBitmap fNoiseBitmap; 152 SkBitmap fImprovedPermutationsBitmap; 153 SkBitmap fGradientBitmap; 154 #endif 155 156 inline int random() { 157 static const int gRandAmplitude = 16807; // 7**5; primitive root of m 158 static const int gRandQ = 127773; // m / a 159 static const int gRandR = 2836; // m % a 160 161 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ); 162 if (result <= 0) 163 result += kRandMaximum; 164 fSeed = result; 165 return result; 166 } 167 168 // Only called once. Could be part of the constructor. 169 void init(SkScalar seed) 170 { 171 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize)); 172 173 // According to the SVG spec, we must truncate (not round) the seed value. 174 fSeed = SkScalarTruncToInt(seed); 175 // The seed value clamp to the range [1, kRandMaximum - 1]. 176 if (fSeed <= 0) { 177 fSeed = -(fSeed % (kRandMaximum - 1)) + 1; 178 } 179 if (fSeed > kRandMaximum - 1) { 180 fSeed = kRandMaximum - 1; 181 } 182 for (int channel = 0; channel < 4; ++channel) { 183 for (int i = 0; i < kBlockSize; ++i) { 184 fLatticeSelector[i] = i; 185 fNoise[channel][i][0] = (random() % (2 * kBlockSize)); 186 fNoise[channel][i][1] = (random() % (2 * kBlockSize)); 187 } 188 } 189 for (int i = kBlockSize - 1; i > 0; --i) { 190 int k = fLatticeSelector[i]; 191 int j = random() % kBlockSize; 192 SkASSERT(j >= 0); 193 SkASSERT(j < kBlockSize); 194 fLatticeSelector[i] = fLatticeSelector[j]; 195 fLatticeSelector[j] = k; 196 } 197 198 // Perform the permutations now 199 { 200 // Copy noise data 201 uint16_t noise[4][kBlockSize][2]; 202 for (int i = 0; i < kBlockSize; ++i) { 203 for (int channel = 0; channel < 4; ++channel) { 204 for (int j = 0; j < 2; ++j) { 205 noise[channel][i][j] = fNoise[channel][i][j]; 206 } 207 } 208 } 209 // Do permutations on noise data 210 for (int i = 0; i < kBlockSize; ++i) { 211 for (int channel = 0; channel < 4; ++channel) { 212 for (int j = 0; j < 2; ++j) { 213 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j]; 214 } 215 } 216 } 217 } 218 219 // Half of the largest possible value for 16 bit unsigned int 220 static const SkScalar gHalfMax16bits = 32767.5f; 221 222 // Compute gradients from permutated noise data 223 for (int channel = 0; channel < 4; ++channel) { 224 for (int i = 0; i < kBlockSize; ++i) { 225 fGradient[channel][i] = SkPoint::Make( 226 (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef, 227 (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef); 228 fGradient[channel][i].normalize(); 229 // Put the normalized gradient back into the noise data 230 fNoise[channel][i][0] = SkScalarRoundToInt( 231 (fGradient[channel][i].fX + 1) * gHalfMax16bits); 232 fNoise[channel][i][1] = SkScalarRoundToInt( 233 (fGradient[channel][i].fY + 1) * gHalfMax16bits); 234 } 235 } 236 } 237 238 // Only called once. Could be part of the constructor. 239 void stitch() { 240 SkScalar tileWidth = SkIntToScalar(fTileSize.width()); 241 SkScalar tileHeight = SkIntToScalar(fTileSize.height()); 242 SkASSERT(tileWidth > 0 && tileHeight > 0); 243 // When stitching tiled turbulence, the frequencies must be adjusted 244 // so that the tile borders will be continuous. 245 if (fBaseFrequency.fX) { 246 SkScalar lowFrequencx = 247 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 248 SkScalar highFrequencx = 249 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 250 // BaseFrequency should be non-negative according to the standard. 251 if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) { 252 fBaseFrequency.fX = lowFrequencx; 253 } else { 254 fBaseFrequency.fX = highFrequencx; 255 } 256 } 257 if (fBaseFrequency.fY) { 258 SkScalar lowFrequency = 259 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 260 SkScalar highFrequency = 261 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 262 if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) { 263 fBaseFrequency.fY = lowFrequency; 264 } else { 265 fBaseFrequency.fY = highFrequency; 266 } 267 } 268 // Set up TurbulenceInitial stitch values. 269 fStitchDataInit.fWidth = 270 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX); 271 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth; 272 fStitchDataInit.fHeight = 273 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); 274 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; 275 } 276 277 public: 278 279#if SK_SUPPORT_GPU 280 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; } 281 282 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } 283 284 const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPermutationsBitmap; } 285 286 const SkBitmap& getGradientBitmap() const { return fGradientBitmap; } 287#endif 288 }; 289 290 /** 291 * About the noise types : the difference between the first 2 is just minor tweaks to the 292 * algorithm, they're not 2 entirely different noises. The output looks different, but once the 293 * noise is generated in the [1, -1] range, the output is brought back in the [0, 1] range by 294 * doing : 295 * kFractalNoise_Type : noise * 0.5 + 0.5 296 * kTurbulence_Type : abs(noise) 297 * Very little differences between the 2 types, although you can tell the difference visually. 298 * "Improved" is based on the Improved Perlin Noise algorithm described at 299 * http://mrl.nyu.edu/~perlin/noise/. It is quite distinct from the other two, and the noise is 300 * a 2D slice of a 3D noise texture. Minor changes to the Z coordinate will result in minor 301 * changes to the noise, making it suitable for animated noise. 302 */ 303 enum Type { 304 kFractalNoise_Type, 305 kTurbulence_Type, 306 kImprovedNoise_Type, 307 kFirstType = kFractalNoise_Type, 308 kLastType = kImprovedNoise_Type 309 }; 310 311 SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::Type type, SkScalar baseFrequencyX, 312 SkScalar baseFrequencyY, int numOctaves, SkScalar seed, 313 const SkISize* tileSize); 314 315 class PerlinNoiseShaderContext : public Context { 316 public: 317 PerlinNoiseShaderContext(const SkPerlinNoiseShaderImpl& shader, const ContextRec&); 318 319 void shadeSpan(int x, int y, SkPMColor[], int count) override; 320 321 private: 322 SkPMColor shade(const SkPoint& point, StitchData& stitchData) const; 323 SkScalar calculateTurbulenceValueForPoint( 324 int channel, 325 StitchData& stitchData, const SkPoint& point) const; 326 SkScalar calculateImprovedNoiseValueForPoint(int channel, const SkPoint& point) const; 327 SkScalar noise2D(int channel, 328 const StitchData& stitchData, const SkPoint& noiseVector) const; 329 330 SkMatrix fMatrix; 331 PaintingData fPaintingData; 332 333 typedef Context INHERITED; 334 }; 335 336#if SK_SUPPORT_GPU 337 sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override; 338#endif 339 340 SK_TO_STRING_OVERRIDE() 341 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkPerlinNoiseShaderImpl) 342 343protected: 344 void flatten(SkWriteBuffer&) const override; 345 Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override; 346 347private: 348 const SkPerlinNoiseShaderImpl::Type fType; 349 const SkScalar fBaseFrequencyX; 350 const SkScalar fBaseFrequencyY; 351 const int fNumOctaves; 352 const SkScalar fSeed; 353 const SkISize fTileSize; 354 const bool fStitchTiles; 355 356 friend class ::SkPerlinNoiseShader; 357 358 typedef SkShaderBase INHERITED; 359}; 360 361namespace { 362 363// noiseValue is the color component's value (or color) 364// limitValue is the maximum perlin noise array index value allowed 365// newValue is the current noise dimension (either width or height) 366inline int checkNoise(int noiseValue, int limitValue, int newValue) { 367 // If the noise value would bring us out of bounds of the current noise array while we are 368 // stiching noise tiles together, wrap the noise around the current dimension of the noise to 369 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible) 370 if (noiseValue >= limitValue) { 371 noiseValue -= newValue; 372 } 373 return noiseValue; 374} 375 376inline SkScalar smoothCurve(SkScalar t) { 377 return t * t * (3 - 2 * t); 378} 379 380} // end namespace 381 382SkPerlinNoiseShaderImpl::SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::Type type, 383 SkScalar baseFrequencyX, 384 SkScalar baseFrequencyY, 385 int numOctaves, 386 SkScalar seed, 387 const SkISize* tileSize) 388 : fType(type) 389 , fBaseFrequencyX(baseFrequencyX) 390 , fBaseFrequencyY(baseFrequencyY) 391 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) 392 , fSeed(seed) 393 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize) 394 , fStitchTiles(!fTileSize.isEmpty()) 395{ 396 SkASSERT(numOctaves >= 0 && numOctaves < 256); 397} 398 399sk_sp<SkFlattenable> SkPerlinNoiseShaderImpl::CreateProc(SkReadBuffer& buffer) { 400 Type type = (Type)buffer.readInt(); 401 SkScalar freqX = buffer.readScalar(); 402 SkScalar freqY = buffer.readScalar(); 403 int octaves = buffer.readInt(); 404 SkScalar seed = buffer.readScalar(); 405 SkISize tileSize; 406 tileSize.fWidth = buffer.readInt(); 407 tileSize.fHeight = buffer.readInt(); 408 409 switch (type) { 410 case kFractalNoise_Type: 411 return SkPerlinNoiseShader::MakeFractalNoise(freqX, freqY, octaves, seed, &tileSize); 412 case kTurbulence_Type: 413 return SkPerlinNoiseShader::MakeTurbulence(freqX, freqY, octaves, seed, &tileSize); 414 case kImprovedNoise_Type: 415 return SkPerlinNoiseShader::MakeImprovedNoise(freqX, freqY, octaves, seed); 416 default: 417 return nullptr; 418 } 419} 420 421void SkPerlinNoiseShaderImpl::flatten(SkWriteBuffer& buffer) const { 422 buffer.writeInt((int) fType); 423 buffer.writeScalar(fBaseFrequencyX); 424 buffer.writeScalar(fBaseFrequencyY); 425 buffer.writeInt(fNumOctaves); 426 buffer.writeScalar(fSeed); 427 buffer.writeInt(fTileSize.fWidth); 428 buffer.writeInt(fTileSize.fHeight); 429} 430 431SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::noise2D( 432 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { 433 struct Noise { 434 int noisePositionIntegerValue; 435 int nextNoisePositionIntegerValue; 436 SkScalar noisePositionFractionValue; 437 Noise(SkScalar component) 438 { 439 SkScalar position = component + kPerlinNoise; 440 noisePositionIntegerValue = SkScalarFloorToInt(position); 441 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); 442 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; 443 } 444 }; 445 Noise noiseX(noiseVector.x()); 446 Noise noiseY(noiseVector.y()); 447 SkScalar u, v; 448 const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader); 449 // If stitching, adjust lattice points accordingly. 450 if (perlinNoiseShader.fStitchTiles) { 451 noiseX.noisePositionIntegerValue = 452 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 453 noiseY.noisePositionIntegerValue = 454 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 455 noiseX.nextNoisePositionIntegerValue = 456 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 457 noiseY.nextNoisePositionIntegerValue = 458 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 459 } 460 noiseX.noisePositionIntegerValue &= kBlockMask; 461 noiseY.noisePositionIntegerValue &= kBlockMask; 462 noiseX.nextNoisePositionIntegerValue &= kBlockMask; 463 noiseY.nextNoisePositionIntegerValue &= kBlockMask; 464 int i = fPaintingData.fLatticeSelector[noiseX.noisePositionIntegerValue]; 465 int j = fPaintingData.fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; 466 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; 467 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; 468 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 469 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 470 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); 471 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); 472 473 if (sx < 0 || sy < 0 || sx > 1 || sy > 1) { 474 return 0; // Check for pathological inputs. 475 } 476 477 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement 478 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, 479 noiseY.noisePositionFractionValue); // Offset (0,0) 480 u = fPaintingData.fGradient[channel][b00].dot(fractionValue); 481 fractionValue.fX -= SK_Scalar1; // Offset (-1,0) 482 v = fPaintingData.fGradient[channel][b10].dot(fractionValue); 483 SkScalar a = SkScalarInterp(u, v, sx); 484 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 485 v = fPaintingData.fGradient[channel][b11].dot(fractionValue); 486 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 487 u = fPaintingData.fGradient[channel][b01].dot(fractionValue); 488 SkScalar b = SkScalarInterp(u, v, sx); 489 return SkScalarInterp(a, b, sy); 490} 491 492SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( 493 int channel, StitchData& stitchData, const SkPoint& point) const { 494 const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader); 495 if (perlinNoiseShader.fStitchTiles) { 496 // Set up TurbulenceInitial stitch values. 497 stitchData = fPaintingData.fStitchDataInit; 498 } 499 SkScalar turbulenceFunctionResult = 0; 500 SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData.fBaseFrequency.fX, 501 point.y() * fPaintingData.fBaseFrequency.fY)); 502 SkScalar ratio = SK_Scalar1; 503 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { 504 SkScalar noise = noise2D(channel, stitchData, noiseVector); 505 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ? 506 noise : SkScalarAbs(noise); 507 turbulenceFunctionResult += numer / ratio; 508 noiseVector.fX *= 2; 509 noiseVector.fY *= 2; 510 ratio *= 2; 511 if (perlinNoiseShader.fStitchTiles) { 512 // Update stitch values 513 stitchData.fWidth *= 2; 514 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 515 stitchData.fHeight *= 2; 516 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; 517 } 518 } 519 520 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 521 // by fractalNoise and (turbulenceFunctionResult) by turbulence. 522 if (perlinNoiseShader.fType == kFractalNoise_Type) { 523 turbulenceFunctionResult = SkScalarHalf(turbulenceFunctionResult + 1); 524 } 525 526 if (channel == 3) { // Scale alpha by paint value 527 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; 528 } 529 530 // Clamp result 531 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 532} 533 534//////////////////////////////////////////////////////////////////////////////////////////////////// 535// Improved Perlin Noise based on Java implementation found at http://mrl.nyu.edu/~perlin/noise/ 536static SkScalar fade(SkScalar t) { 537 return t * t * t * (t * (t * 6 - 15) + 10); 538} 539 540static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) { 541 return a + t * (b - a); 542} 543 544static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) { 545 int h = hash & 15; 546 SkScalar u = h < 8 ? x : y; 547 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z; 548 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); 549} 550 551SkScalar SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::calculateImprovedNoiseValueForPoint( 552 int channel, const SkPoint& point) const { 553 const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader); 554 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX; 555 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY; 556 // z offset between different channels, chosen arbitrarily 557 static const SkScalar CHANNEL_DELTA = 1000.0f; 558 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed; 559 SkScalar result = 0; 560 SkScalar ratio = SK_Scalar1; 561 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) { 562 int X = SkScalarFloorToInt(x) & 255; 563 int Y = SkScalarFloorToInt(y) & 255; 564 int Z = SkScalarFloorToInt(z) & 255; 565 SkScalar px = x - SkScalarFloorToScalar(x); 566 SkScalar py = y - SkScalarFloorToScalar(y); 567 SkScalar pz = z - SkScalarFloorToScalar(z); 568 SkScalar u = fade(px); 569 SkScalar v = fade(py); 570 SkScalar w = fade(pz); 571 uint8_t* permutations = improved_noise_permutations; 572 int A = permutations[X] + Y; 573 int AA = permutations[A] + Z; 574 int AB = permutations[A + 1] + Z; 575 int B = permutations[X + 1] + Y; 576 int BA = permutations[B] + Z; 577 int BB = permutations[B + 1] + Z; 578 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py , pz ), 579 grad(permutations[BA ], px - 1, py , pz )), 580 lerp(u, grad(permutations[AB ], px , py - 1, pz ), 581 grad(permutations[BB ], px - 1, py - 1, pz ))), 582 lerp(v, lerp(u, grad(permutations[AA + 1], px , py , pz - 1), 583 grad(permutations[BA + 1], px - 1, py , pz - 1)), 584 lerp(u, grad(permutations[AB + 1], px , py - 1, pz - 1), 585 grad(permutations[BB + 1], px - 1, py - 1, pz - 1)))) / 586 ratio; 587 x *= 2; 588 y *= 2; 589 ratio *= 2; 590 } 591 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f); 592 return result; 593} 594//////////////////////////////////////////////////////////////////////////////////////////////////// 595 596SkPMColor SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shade( 597 const SkPoint& point, StitchData& stitchData) const { 598 const SkPerlinNoiseShaderImpl& perlinNoiseShader = static_cast<const SkPerlinNoiseShaderImpl&>(fShader); 599 SkPoint newPoint; 600 fMatrix.mapPoints(&newPoint, &point, 1); 601 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 602 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 603 604 U8CPU rgba[4]; 605 for (int channel = 3; channel >= 0; --channel) { 606 SkScalar value; 607 if (perlinNoiseShader.fType == kImprovedNoise_Type) { 608 value = calculateImprovedNoiseValueForPoint(channel, newPoint); 609 } 610 else { 611 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoint); 612 } 613 rgba[channel] = SkScalarFloorToInt(255 * value); 614 } 615 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 616} 617 618SkShaderBase::Context* SkPerlinNoiseShaderImpl::onMakeContext(const ContextRec& rec, 619 SkArenaAlloc* alloc) const { 620 return alloc->make<PerlinNoiseShaderContext>(*this, rec); 621} 622 623static inline SkMatrix total_matrix(const SkShaderBase::ContextRec& rec, 624 const SkShaderBase& shader) { 625 SkMatrix matrix = SkMatrix::Concat(*rec.fMatrix, shader.getLocalMatrix()); 626 if (rec.fLocalMatrix) { 627 matrix.preConcat(*rec.fLocalMatrix); 628 } 629 630 return matrix; 631} 632 633SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::PerlinNoiseShaderContext( 634 const SkPerlinNoiseShaderImpl& shader, const ContextRec& rec) 635 : INHERITED(shader, rec) 636 , fMatrix(total_matrix(rec, shader)) // used for temp storage, adjusted below 637 , fPaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, 638 shader.fBaseFrequencyY, fMatrix) 639{ 640 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise 641 // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 642 fMatrix.setTranslate(-fMatrix.getTranslateX() + SK_Scalar1, 643 -fMatrix.getTranslateY() + SK_Scalar1); 644} 645 646void SkPerlinNoiseShaderImpl::PerlinNoiseShaderContext::shadeSpan( 647 int x, int y, SkPMColor result[], int count) { 648 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 649 StitchData stitchData; 650 for (int i = 0; i < count; ++i) { 651 result[i] = shade(point, stitchData); 652 point.fX += SK_Scalar1; 653 } 654} 655 656///////////////////////////////////////////////////////////////////// 657 658#if SK_SUPPORT_GPU 659 660class GrGLPerlinNoise : public GrGLSLFragmentProcessor { 661public: 662 void emitCode(EmitArgs&) override; 663 664 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b); 665 666protected: 667 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; 668 669private: 670 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; 671 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; 672 673 typedef GrGLSLFragmentProcessor INHERITED; 674}; 675 676///////////////////////////////////////////////////////////////////// 677 678class GrPerlinNoise2Effect : public GrFragmentProcessor { 679public: 680 static sk_sp<GrFragmentProcessor> Make(SkPerlinNoiseShaderImpl::Type type, 681 int numOctaves, bool stitchTiles, 682 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData, 683 sk_sp<GrTextureProxy> permutationsProxy, 684 sk_sp<GrTextureProxy> noiseProxy, 685 const SkMatrix& matrix) { 686 return sk_sp<GrFragmentProcessor>( 687 new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, 688 std::move(paintingData), 689 std::move(permutationsProxy), std::move(noiseProxy), matrix)); 690 } 691 692 const char* name() const override { return "PerlinNoise"; } 693 694 const SkPerlinNoiseShaderImpl::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; } 695 696 SkPerlinNoiseShaderImpl::Type type() const { return fType; } 697 bool stitchTiles() const { return fStitchTiles; } 698 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; } 699 int numOctaves() const { return fNumOctaves; } 700 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } 701 702private: 703 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 704 return new GrGLPerlinNoise; 705 } 706 707 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, 708 GrProcessorKeyBuilder* b) const override { 709 GrGLPerlinNoise::GenKey(*this, caps, b); 710 } 711 712 bool onIsEqual(const GrFragmentProcessor& sBase) const override { 713 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>(); 714 return fType == s.fType && 715 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency && 716 fNumOctaves == s.fNumOctaves && 717 fStitchTiles == s.fStitchTiles && 718 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit; 719 } 720 721 GrPerlinNoise2Effect(SkPerlinNoiseShaderImpl::Type type, int numOctaves, bool stitchTiles, 722 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData, 723 sk_sp<GrTextureProxy> permutationsProxy, 724 sk_sp<GrTextureProxy> noiseProxy, 725 const SkMatrix& matrix) 726 : INHERITED(kNone_OptimizationFlags) 727 , fType(type) 728 , fNumOctaves(numOctaves) 729 , fStitchTiles(stitchTiles) 730 , fPermutationsSampler(std::move(permutationsProxy)) 731 , fNoiseSampler(std::move(noiseProxy)) 732 , fPaintingData(std::move(paintingData)) { 733 this->initClassID<GrPerlinNoise2Effect>(); 734 this->addTextureSampler(&fPermutationsSampler); 735 this->addTextureSampler(&fNoiseSampler); 736 fCoordTransform.reset(matrix); 737 this->addCoordTransform(&fCoordTransform); 738 } 739 740 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 741 742 SkPerlinNoiseShaderImpl::Type fType; 743 GrCoordTransform fCoordTransform; 744 int fNumOctaves; 745 bool fStitchTiles; 746 TextureSampler fPermutationsSampler; 747 TextureSampler fNoiseSampler; 748 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData; 749 750 typedef GrFragmentProcessor INHERITED; 751}; 752 753///////////////////////////////////////////////////////////////////// 754GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect); 755 756#if GR_TEST_UTILS 757sk_sp<GrFragmentProcessor> GrPerlinNoise2Effect::TestCreate(GrProcessorTestData* d) { 758 int numOctaves = d->fRandom->nextRangeU(2, 10); 759 bool stitchTiles = d->fRandom->nextBool(); 760 SkScalar seed = SkIntToScalar(d->fRandom->nextU()); 761 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096), 762 d->fRandom->nextRangeU(4, 4096)); 763 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, 764 0.99f); 765 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, 766 0.99f); 767 768 sk_sp<SkShader> shader(d->fRandom->nextBool() ? 769 SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed, 770 stitchTiles ? &tileSize : nullptr) : 771 SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed, 772 stitchTiles ? &tileSize : nullptr)); 773 774 GrTest::TestAsFPArgs asFPArgs(d); 775 return as_SB(shader)->asFragmentProcessor(asFPArgs.args()); 776} 777#endif 778 779void GrGLPerlinNoise::emitCode(EmitArgs& args) { 780 const GrPerlinNoise2Effect& pne = args.fFp.cast<GrPerlinNoise2Effect>(); 781 782 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 783 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 784 SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); 785 786 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 787 kVec2f_GrSLType, kDefault_GrSLPrecision, 788 "baseFrequency"); 789 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni); 790 791 const char* stitchDataUni = nullptr; 792 if (pne.stitchTiles()) { 793 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 794 kVec2f_GrSLType, kDefault_GrSLPrecision, 795 "stitchData"); 796 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni); 797 } 798 799 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 800 const char* chanCoordR = "0.125"; 801 const char* chanCoordG = "0.375"; 802 const char* chanCoordB = "0.625"; 803 const char* chanCoordA = "0.875"; 804 const char* chanCoord = "chanCoord"; 805 const char* stitchData = "stitchData"; 806 const char* ratio = "ratio"; 807 const char* noiseVec = "noiseVec"; 808 const char* noiseSmooth = "noiseSmooth"; 809 const char* floorVal = "floorVal"; 810 const char* fractVal = "fractVal"; 811 const char* uv = "uv"; 812 const char* ab = "ab"; 813 const char* latticeIdx = "latticeIdx"; 814 const char* bcoords = "bcoords"; 815 const char* lattice = "lattice"; 816 const char* inc8bit = "0.00390625"; // 1.0 / 256.0 817 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a 818 // [-1,1] vector and perform a dot product between that vector and the provided vector. 819 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);"; 820 821 // Add noise function 822 static const GrShaderVar gPerlinNoiseArgs[] = { 823 GrShaderVar(chanCoord, kFloat_GrSLType), 824 GrShaderVar(noiseVec, kVec2f_GrSLType) 825 }; 826 827 static const GrShaderVar gPerlinNoiseStitchArgs[] = { 828 GrShaderVar(chanCoord, kFloat_GrSLType), 829 GrShaderVar(noiseVec, kVec2f_GrSLType), 830 GrShaderVar(stitchData, kVec2f_GrSLType) 831 }; 832 833 SkString noiseCode; 834 835 noiseCode.appendf("\tvec4 %s;\n", floorVal); 836 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); 837 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); 838 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); 839 840 // smooth curve : t * t * (3 - 2 * t) 841 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", 842 noiseSmooth, fractVal, fractVal, fractVal); 843 844 // Adjust frequencies if we're stitching tiles 845 if (pne.stitchTiles()) { 846 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", 847 floorVal, stitchData, floorVal, stitchData); 848 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", 849 floorVal, stitchData, floorVal, stitchData); 850 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", 851 floorVal, stitchData, floorVal, stitchData); 852 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", 853 floorVal, stitchData, floorVal, stitchData); 854 } 855 856 // Get texture coordinates and normalize 857 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n", 858 floorVal, floorVal); 859 860 // Get permutation for x 861 { 862 SkString xCoords(""); 863 xCoords.appendf("vec2(%s.x, 0.5)", floorVal); 864 865 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); 866 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), 867 kVec2f_GrSLType); 868 noiseCode.append(".r;"); 869 } 870 871 // Get permutation for x + 1 872 { 873 SkString xCoords(""); 874 xCoords.appendf("vec2(%s.z, 0.5)", floorVal); 875 876 noiseCode.appendf("\n\t%s.y = ", latticeIdx); 877 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), 878 kVec2f_GrSLType); 879 noiseCode.append(".r;"); 880 } 881 882#if defined(SK_BUILD_FOR_ANDROID) 883 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). 884 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit 885 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 886 // (or 0.484368 here). The following rounding operation prevents these precision issues from 887 // affecting the result of the noise by making sure that we only have multiples of 1/255. 888 // (Note that 1/255 is about 0.003921569, which is the value used here). 889 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", 890 latticeIdx, latticeIdx); 891#endif 892 893 // Get (x,y) coordinates with the permutated x 894 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); 895 896 noiseCode.appendf("\n\n\tvec2 %s;", uv); 897 // Compute u, at offset (0,0) 898 { 899 SkString latticeCoords(""); 900 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); 901 noiseCode.appendf("\n\tvec4 %s = ", lattice); 902 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 903 kVec2f_GrSLType); 904 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 905 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 906 } 907 908 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); 909 // Compute v, at offset (-1,0) 910 { 911 SkString latticeCoords(""); 912 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); 913 noiseCode.append("\n\tlattice = "); 914 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 915 kVec2f_GrSLType); 916 noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 917 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 918 } 919 920 // Compute 'a' as a linear interpolation of 'u' and 'v' 921 noiseCode.appendf("\n\tvec2 %s;", ab); 922 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 923 924 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); 925 // Compute v, at offset (-1,-1) 926 { 927 SkString latticeCoords(""); 928 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); 929 noiseCode.append("\n\tlattice = "); 930 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 931 kVec2f_GrSLType); 932 noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 933 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 934 } 935 936 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); 937 // Compute u, at offset (0,-1) 938 { 939 SkString latticeCoords(""); 940 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); 941 noiseCode.append("\n\tlattice = "); 942 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 943 kVec2f_GrSLType); 944 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 945 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 946 } 947 948 // Compute 'b' as a linear interpolation of 'u' and 'v' 949 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 950 // Compute the noise as a linear interpolation of 'a' and 'b' 951 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); 952 953 SkString noiseFuncName; 954 if (pne.stitchTiles()) { 955 fragBuilder->emitFunction(kFloat_GrSLType, 956 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), 957 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); 958 } else { 959 fragBuilder->emitFunction(kFloat_GrSLType, 960 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), 961 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); 962 } 963 964 // There are rounding errors if the floor operation is not performed here 965 fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", 966 noiseVec, vCoords.c_str(), baseFrequencyUni); 967 968 // Clear the color accumulator 969 fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor); 970 971 if (pne.stitchTiles()) { 972 // Set up TurbulenceInitial stitch values. 973 fragBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); 974 } 975 976 fragBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); 977 978 // Loop over all octaves 979 fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves()); 980 981 fragBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor); 982 if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) { 983 fragBuilder->codeAppend("abs("); 984 } 985 if (pne.stitchTiles()) { 986 fragBuilder->codeAppendf( 987 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," 988 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", 989 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, 990 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, 991 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, 992 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); 993 } else { 994 fragBuilder->codeAppendf( 995 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," 996 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", 997 noiseFuncName.c_str(), chanCoordR, noiseVec, 998 noiseFuncName.c_str(), chanCoordG, noiseVec, 999 noiseFuncName.c_str(), chanCoordB, noiseVec, 1000 noiseFuncName.c_str(), chanCoordA, noiseVec); 1001 } 1002 if (pne.type() != SkPerlinNoiseShaderImpl::kFractalNoise_Type) { 1003 fragBuilder->codeAppendf(")"); // end of "abs(" 1004 } 1005 fragBuilder->codeAppendf(" * %s;", ratio); 1006 1007 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); 1008 fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); 1009 1010 if (pne.stitchTiles()) { 1011 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); 1012 } 1013 fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves 1014 1015 if (pne.type() == SkPerlinNoiseShaderImpl::kFractalNoise_Type) { 1016 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 1017 // by fractalNoise and (turbulenceFunctionResult) by turbulence. 1018 fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", 1019 args.fOutputColor,args.fOutputColor); 1020 } 1021 1022 // Clamp values 1023 fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor); 1024 1025 // Pre-multiply the result 1026 fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", 1027 args.fOutputColor, args.fOutputColor, 1028 args.fOutputColor, args.fOutputColor); 1029} 1030 1031void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&, 1032 GrProcessorKeyBuilder* b) { 1033 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>(); 1034 1035 uint32_t key = turbulence.numOctaves(); 1036 1037 key = key << 3; // Make room for next 3 bits 1038 1039 switch (turbulence.type()) { 1040 case SkPerlinNoiseShaderImpl::kFractalNoise_Type: 1041 key |= 0x1; 1042 break; 1043 case SkPerlinNoiseShaderImpl::kTurbulence_Type: 1044 key |= 0x2; 1045 break; 1046 default: 1047 // leave key at 0 1048 break; 1049 } 1050 1051 if (turbulence.stitchTiles()) { 1052 key |= 0x4; // Flip the 3rd bit if tile stitching is on 1053 } 1054 1055 b->add32(key); 1056} 1057 1058void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman, 1059 const GrFragmentProcessor& processor) { 1060 INHERITED::onSetData(pdman, processor); 1061 1062 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect>(); 1063 1064 const SkVector& baseFrequency = turbulence.baseFrequency(); 1065 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); 1066 1067 if (turbulence.stitchTiles()) { 1068 const SkPerlinNoiseShaderImpl::StitchData& stitchData = turbulence.stitchData(); 1069 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), 1070 SkIntToScalar(stitchData.fHeight)); 1071 } 1072} 1073 1074///////////////////////////////////////////////////////////////////// 1075 1076class GrGLImprovedPerlinNoise : public GrGLSLFragmentProcessor { 1077public: 1078 void emitCode(EmitArgs&) override; 1079 1080 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*); 1081 1082protected: 1083 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override; 1084 1085private: 1086 GrGLSLProgramDataManager::UniformHandle fZUni; 1087 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; 1088 1089 typedef GrGLSLFragmentProcessor INHERITED; 1090}; 1091 1092///////////////////////////////////////////////////////////////////// 1093 1094class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor { 1095public: 1096 static sk_sp<GrFragmentProcessor> Make(int octaves, SkScalar z, 1097 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData, 1098 sk_sp<GrTextureProxy> permutationsProxy, 1099 sk_sp<GrTextureProxy> gradientProxy, 1100 const SkMatrix& matrix) { 1101 return sk_sp<GrFragmentProcessor>( 1102 new GrImprovedPerlinNoiseEffect(octaves, z, std::move(paintingData), 1103 std::move(permutationsProxy), 1104 std::move(gradientProxy), matrix)); 1105 } 1106 1107 const char* name() const override { return "ImprovedPerlinNoise"; } 1108 1109 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; } 1110 SkScalar z() const { return fZ; } 1111 int octaves() const { return fOctaves; } 1112 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } 1113 1114private: 1115 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 1116 return new GrGLImprovedPerlinNoise; 1117 } 1118 1119 void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override { 1120 GrGLImprovedPerlinNoise::GenKey(*this, caps, b); 1121 } 1122 1123 bool onIsEqual(const GrFragmentProcessor& sBase) const override { 1124 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseEffect>(); 1125 return fZ == fZ && 1126 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency; 1127 } 1128 1129 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z, 1130 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData, 1131 sk_sp<GrTextureProxy> permutationsProxy, 1132 sk_sp<GrTextureProxy> gradientProxy, 1133 const SkMatrix& matrix) 1134 : INHERITED(kNone_OptimizationFlags) 1135 , fOctaves(octaves) 1136 , fZ(z) 1137 , fPermutationsSampler(std::move(permutationsProxy)) 1138 , fGradientSampler(std::move(gradientProxy)) 1139 , fPaintingData(std::move(paintingData)) { 1140 this->initClassID<GrImprovedPerlinNoiseEffect>(); 1141 this->addTextureSampler(&fPermutationsSampler); 1142 this->addTextureSampler(&fGradientSampler); 1143 fCoordTransform.reset(matrix); 1144 this->addCoordTransform(&fCoordTransform); 1145 } 1146 1147 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 1148 1149 GrCoordTransform fCoordTransform; 1150 int fOctaves; 1151 SkScalar fZ; 1152 TextureSampler fPermutationsSampler; 1153 TextureSampler fGradientSampler; 1154 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> fPaintingData; 1155 1156 typedef GrFragmentProcessor INHERITED; 1157}; 1158 1159///////////////////////////////////////////////////////////////////// 1160GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect); 1161 1162#if GR_TEST_UTILS 1163sk_sp<GrFragmentProcessor> GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) { 1164 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, 1165 0.99f); 1166 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, 1167 0.99f); 1168 int numOctaves = d->fRandom->nextRangeU(2, 10); 1169 SkScalar z = SkIntToScalar(d->fRandom->nextU()); 1170 1171 sk_sp<SkShader> shader(SkPerlinNoiseShader::MakeImprovedNoise(baseFrequencyX, 1172 baseFrequencyY, 1173 numOctaves, 1174 z)); 1175 1176 GrTest::TestAsFPArgs asFPArgs(d); 1177 return as_SB(shader)->asFragmentProcessor(asFPArgs.args()); 1178} 1179#endif 1180 1181void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) { 1182 const GrImprovedPerlinNoiseEffect& pne = args.fFp.cast<GrImprovedPerlinNoiseEffect>(); 1183 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder; 1184 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 1185 SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); 1186 1187 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 1188 kVec2f_GrSLType, kDefault_GrSLPrecision, 1189 "baseFrequency"); 1190 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni); 1191 1192 fZUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 1193 kFloat_GrSLType, kDefault_GrSLPrecision, 1194 "z"); 1195 const char* zUni = uniformHandler->getUniformCStr(fZUni); 1196 1197 // fade function 1198 static const GrShaderVar fadeArgs[] = { 1199 GrShaderVar("t", kVec3f_GrSLType) 1200 }; 1201 SkString fadeFuncName; 1202 fragBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs), 1203 fadeArgs, 1204 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);", 1205 &fadeFuncName); 1206 1207 // perm function 1208 static const GrShaderVar permArgs[] = { 1209 GrShaderVar("x", kFloat_GrSLType) 1210 }; 1211 SkString permFuncName; 1212 SkString permCode("return "); 1213 // FIXME even though I'm creating these textures with kRepeat_TileMode, they're clamped. Not 1214 // sure why. Using fract() (here and the next texture lookup) as a workaround. 1215 fragBuilder->appendTextureLookup(&permCode, args.fTexSamplers[0], "vec2(fract(x / 256.0), 0.0)", 1216 kVec2f_GrSLType); 1217 permCode.append(".r * 255.0;"); 1218 fragBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), permArgs, 1219 permCode.c_str(), &permFuncName); 1220 1221 // grad function 1222 static const GrShaderVar gradArgs[] = { 1223 GrShaderVar("x", kFloat_GrSLType), 1224 GrShaderVar("p", kVec3f_GrSLType) 1225 }; 1226 SkString gradFuncName; 1227 SkString gradCode("return dot("); 1228 fragBuilder->appendTextureLookup(&gradCode, args.fTexSamplers[1], "vec2(fract(x / 16.0), 0.0)", 1229 kVec2f_GrSLType); 1230 gradCode.append(".rgb * 255.0 - vec3(1.0), p);"); 1231 fragBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), gradArgs, 1232 gradCode.c_str(), &gradFuncName); 1233 1234 // lerp function 1235 static const GrShaderVar lerpArgs[] = { 1236 GrShaderVar("a", kFloat_GrSLType), 1237 GrShaderVar("b", kFloat_GrSLType), 1238 GrShaderVar("w", kFloat_GrSLType) 1239 }; 1240 SkString lerpFuncName; 1241 fragBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), lerpArgs, 1242 "return a + w * (b - a);", &lerpFuncName); 1243 1244 // noise function 1245 static const GrShaderVar noiseArgs[] = { 1246 GrShaderVar("p", kVec3f_GrSLType), 1247 }; 1248 SkString noiseFuncName; 1249 SkString noiseCode; 1250 noiseCode.append("vec3 P = mod(floor(p), 256.0);"); 1251 noiseCode.append("p -= floor(p);"); 1252 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str()); 1253 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str()); 1254 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str()); 1255 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str()); 1256 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str()); 1257 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str()); 1258 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str()); 1259 noiseCode.appendf("float result = %s(", lerpFuncName.c_str()); 1260 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName.c_str(), 1261 gradFuncName.c_str(), permFuncName.c_str()); 1262 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncName.c_str(), 1263 permFuncName.c_str()); 1264 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c_str(), 1265 gradFuncName.c_str(), permFuncName.c_str()); 1266 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),", 1267 gradFuncName.c_str(), permFuncName.c_str()); 1268 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),", 1269 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c_str(), 1270 permFuncName.c_str()); 1271 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),", 1272 gradFuncName.c_str(), permFuncName.c_str()); 1273 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),", 1274 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c_str()); 1275 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y), f.z);", 1276 gradFuncName.c_str(), permFuncName.c_str()); 1277 noiseCode.append("return result;"); 1278 fragBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs), noiseArgs, 1279 noiseCode.c_str(), &noiseFuncName); 1280 1281 // noiseOctaves function 1282 static const GrShaderVar noiseOctavesArgs[] = { 1283 GrShaderVar("p", kVec3f_GrSLType) 1284 }; 1285 SkString noiseOctavesFuncName; 1286 SkString noiseOctavesCode; 1287 noiseOctavesCode.append("float result = 0.0;"); 1288 noiseOctavesCode.append("float ratio = 1.0;"); 1289 noiseOctavesCode.appendf("for (float i = 0.0; i < %d; i++) {", pne.octaves()); 1290 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str()); 1291 noiseOctavesCode.append("p *= 2.0;"); 1292 noiseOctavesCode.append("ratio *= 2.0;"); 1293 noiseOctavesCode.append("}"); 1294 noiseOctavesCode.append("return (result + 1.0) / 2.0;"); 1295 fragBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(noiseOctavesArgs), 1296 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOctavesFuncName); 1297 1298 fragBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFrequencyUni); 1299 fragBuilder->codeAppendf("float r = %s(vec3(coords, %s));", noiseOctavesFuncName.c_str(), 1300 zUni); 1301 fragBuilder->codeAppendf("float g = %s(vec3(coords, %s + 0000.0));", 1302 noiseOctavesFuncName.c_str(), zUni); 1303 fragBuilder->codeAppendf("float b = %s(vec3(coords, %s + 0000.0));", 1304 noiseOctavesFuncName.c_str(), zUni); 1305 fragBuilder->codeAppendf("float a = %s(vec3(coords, %s + 0000.0));", 1306 noiseOctavesFuncName.c_str(), zUni); 1307 fragBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor); 1308 1309 // Clamp values 1310 fragBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor); 1311 1312 // Pre-multiply the result 1313 fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", 1314 args.fOutputColor, args.fOutputColor, 1315 args.fOutputColor, args.fOutputColor); 1316} 1317 1318void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&, 1319 GrProcessorKeyBuilder* b) { 1320 const GrImprovedPerlinNoiseEffect& pne = processor.cast<GrImprovedPerlinNoiseEffect>(); 1321 b->add32(pne.octaves()); 1322} 1323 1324void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman, 1325 const GrFragmentProcessor& processor) { 1326 INHERITED::onSetData(pdman, processor); 1327 1328 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNoiseEffect>(); 1329 1330 const SkVector& baseFrequency = noise.baseFrequency(); 1331 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); 1332 1333 pdman.set1f(fZUni, noise.z()); 1334} 1335 1336///////////////////////////////////////////////////////////////////// 1337sk_sp<GrFragmentProcessor> SkPerlinNoiseShaderImpl::asFragmentProcessor(const AsFPArgs& args) const { 1338 SkASSERT(args.fContext); 1339 1340 SkMatrix localMatrix = this->getLocalMatrix(); 1341 if (args.fLocalMatrix) { 1342 localMatrix.preConcat(*args.fLocalMatrix); 1343 } 1344 1345 SkMatrix matrix = *args.fViewMatrix; 1346 matrix.preConcat(localMatrix); 1347 1348 // Either we don't stitch tiles, either we have a valid tile size 1349 SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); 1350 1351 std::unique_ptr<SkPerlinNoiseShaderImpl::PaintingData> paintingData = 1352 skstd::make_unique<SkPerlinNoiseShaderImpl::PaintingData>(fTileSize, 1353 fSeed, 1354 fBaseFrequencyX, 1355 fBaseFrequencyY, 1356 matrix); 1357 1358 SkMatrix m = *args.fViewMatrix; 1359 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); 1360 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); 1361 1362 if (fType == kImprovedNoise_Type) { 1363 GrSamplerParams textureParams(SkShader::TileMode::kRepeat_TileMode, 1364 GrSamplerParams::FilterMode::kNone_FilterMode); 1365 sk_sp<GrTextureProxy> permutationsTexture( 1366 GrRefCachedBitmapTextureProxy(args.fContext, 1367 paintingData->getImprovedPermutationsBitmap(), 1368 textureParams, nullptr)); 1369 sk_sp<GrTextureProxy> gradientTexture( 1370 GrRefCachedBitmapTextureProxy(args.fContext, 1371 paintingData->getGradientBitmap(), 1372 textureParams, nullptr)); 1373 return GrImprovedPerlinNoiseEffect::Make(fNumOctaves, fSeed, std::move(paintingData), 1374 std::move(permutationsTexture), 1375 std::move(gradientTexture), m); 1376 } 1377 1378 if (0 == fNumOctaves) { 1379 if (kFractalNoise_Type == fType) { 1380 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) 1381 // TODO: Either treat the output of this shader as sRGB or allow client to specify a 1382 // color space of the noise. Either way, this case (and the GLSL) need to convert to 1383 // the destination. 1384 sk_sp<GrFragmentProcessor> inner( 1385 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040), 1386 GrConstColorProcessor::kModulateRGBA_InputMode)); 1387 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); 1388 } 1389 // Emit zero. 1390 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(), 1391 GrConstColorProcessor::kIgnore_InputMode); 1392 } 1393 1394 sk_sp<GrTextureProxy> permutationsProxy = GrMakeCachedBitmapProxy( 1395 args.fContext->resourceProvider(), 1396 paintingData->getPermutationsBitmap()); 1397 sk_sp<GrTextureProxy> noiseProxy = GrMakeCachedBitmapProxy(args.fContext->resourceProvider(), 1398 paintingData->getNoiseBitmap()); 1399 1400 if (permutationsProxy && noiseProxy) { 1401 sk_sp<GrFragmentProcessor> inner( 1402 GrPerlinNoise2Effect::Make(fType, 1403 fNumOctaves, 1404 fStitchTiles, 1405 std::move(paintingData), 1406 std::move(permutationsProxy), 1407 std::move(noiseProxy), 1408 m)); 1409 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); 1410 } 1411 return nullptr; 1412} 1413 1414#endif 1415 1416#ifndef SK_IGNORE_TO_STRING 1417void SkPerlinNoiseShaderImpl::toString(SkString* str) const { 1418 str->append("SkPerlinNoiseShaderImpl: ("); 1419 1420 str->append("type: "); 1421 switch (fType) { 1422 case kFractalNoise_Type: 1423 str->append("\"fractal noise\""); 1424 break; 1425 case kTurbulence_Type: 1426 str->append("\"turbulence\""); 1427 break; 1428 default: 1429 str->append("\"unknown\""); 1430 break; 1431 } 1432 str->append(" base frequency: ("); 1433 str->appendScalar(fBaseFrequencyX); 1434 str->append(", "); 1435 str->appendScalar(fBaseFrequencyY); 1436 str->append(") number of octaves: "); 1437 str->appendS32(fNumOctaves); 1438 str->append(" seed: "); 1439 str->appendScalar(fSeed); 1440 str->append(" stitch tiles: "); 1441 str->append(fStitchTiles ? "true " : "false "); 1442 1443 this->INHERITED::toString(str); 1444 1445 str->append(")"); 1446} 1447#endif 1448 1449/////////////////////////////////////////////////////////////////////////////////////////////////// 1450 1451sk_sp<SkShader> SkPerlinNoiseShader::MakeFractalNoise(SkScalar baseFrequencyX, 1452 SkScalar baseFrequencyY, 1453 int numOctaves, SkScalar seed, 1454 const SkISize* tileSize) { 1455 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kFractalNoise_Type, 1456 baseFrequencyX, baseFrequencyY, numOctaves, seed, 1457 tileSize)); 1458} 1459 1460sk_sp<SkShader> SkPerlinNoiseShader::MakeTurbulence(SkScalar baseFrequencyX, 1461 SkScalar baseFrequencyY, 1462 int numOctaves, SkScalar seed, 1463 const SkISize* tileSize) { 1464 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kTurbulence_Type, 1465 baseFrequencyX, baseFrequencyY, numOctaves, seed, 1466 tileSize)); 1467} 1468 1469sk_sp<SkShader> SkPerlinNoiseShader::MakeImprovedNoise(SkScalar baseFrequencyX, 1470 SkScalar baseFrequencyY, 1471 int numOctaves, SkScalar z) { 1472 return sk_sp<SkShader>(new SkPerlinNoiseShaderImpl(SkPerlinNoiseShaderImpl::kImprovedNoise_Type, 1473 baseFrequencyX, baseFrequencyY, numOctaves, z, 1474 nullptr)); 1475} 1476 1477SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkPerlinNoiseShader) 1478 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShaderImpl) 1479SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1480