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