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