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 "SkReadBuffer.h" 13#include "SkWriteBuffer.h" 14#include "SkShader.h" 15#include "SkUnPreMultiply.h" 16#include "SkString.h" 17 18#if SK_SUPPORT_GPU 19#include "GrContext.h" 20#include "GrCoordTransform.h" 21#include "SkGr.h" 22#include "effects/GrConstColorProcessor.h" 23#include "glsl/GrGLSLFragmentProcessor.h" 24#include "glsl/GrGLSLFragmentShaderBuilder.h" 25#include "glsl/GrGLSLProgramDataManager.h" 26#include "glsl/GrGLSLUniformHandler.h" 27#endif 28 29static const int kBlockSize = 256; 30static const int kBlockMask = kBlockSize - 1; 31static const int kPerlinNoise = 4096; 32static const int kRandMaximum = SK_MaxS32; // 2**31 - 1 33 34namespace { 35 36// noiseValue is the color component's value (or color) 37// limitValue is the maximum perlin noise array index value allowed 38// newValue is the current noise dimension (either width or height) 39inline int checkNoise(int noiseValue, int limitValue, int newValue) { 40 // If the noise value would bring us out of bounds of the current noise array while we are 41 // stiching noise tiles together, wrap the noise around the current dimension of the noise to 42 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible) 43 if (noiseValue >= limitValue) { 44 noiseValue -= newValue; 45 } 46 return noiseValue; 47} 48 49inline SkScalar smoothCurve(SkScalar t) { 50 return t * t * (3 - 2 * t); 51} 52 53} // end namespace 54 55struct SkPerlinNoiseShader::StitchData { 56 StitchData() 57 : fWidth(0) 58 , fWrapX(0) 59 , fHeight(0) 60 , fWrapY(0) 61 {} 62 63 bool operator==(const StitchData& other) const { 64 return fWidth == other.fWidth && 65 fWrapX == other.fWrapX && 66 fHeight == other.fHeight && 67 fWrapY == other.fWrapY; 68 } 69 70 int fWidth; // How much to subtract to wrap for stitching. 71 int fWrapX; // Minimum value to wrap. 72 int fHeight; 73 int fWrapY; 74}; 75 76struct SkPerlinNoiseShader::PaintingData { 77 PaintingData(const SkISize& tileSize, SkScalar seed, 78 SkScalar baseFrequencyX, SkScalar baseFrequencyY, 79 const SkMatrix& matrix) 80 { 81 SkVector vec[2] = { 82 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY) }, 83 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight) }, 84 }; 85 matrix.mapVectors(vec, 2); 86 87 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY)); 88 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].fY)); 89 this->init(seed); 90 if (!fTileSize.isEmpty()) { 91 this->stitch(); 92 } 93 94#if SK_SUPPORT_GPU 95 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); 96 fPermutationsBitmap.setPixels(fLatticeSelector); 97 98 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); 99 fNoiseBitmap.setPixels(fNoise[0][0]); 100#endif 101 } 102 103 int fSeed; 104 uint8_t fLatticeSelector[kBlockSize]; 105 uint16_t fNoise[4][kBlockSize][2]; 106 SkPoint fGradient[4][kBlockSize]; 107 SkISize fTileSize; 108 SkVector fBaseFrequency; 109 StitchData fStitchDataInit; 110 111private: 112 113#if SK_SUPPORT_GPU 114 SkBitmap fPermutationsBitmap; 115 SkBitmap fNoiseBitmap; 116#endif 117 118 inline int random() { 119 static const int gRandAmplitude = 16807; // 7**5; primitive root of m 120 static const int gRandQ = 127773; // m / a 121 static const int gRandR = 2836; // m % a 122 123 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ); 124 if (result <= 0) 125 result += kRandMaximum; 126 fSeed = result; 127 return result; 128 } 129 130 // Only called once. Could be part of the constructor. 131 void init(SkScalar seed) 132 { 133 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize)); 134 135 // According to the SVG spec, we must truncate (not round) the seed value. 136 fSeed = SkScalarTruncToInt(seed); 137 // The seed value clamp to the range [1, kRandMaximum - 1]. 138 if (fSeed <= 0) { 139 fSeed = -(fSeed % (kRandMaximum - 1)) + 1; 140 } 141 if (fSeed > kRandMaximum - 1) { 142 fSeed = kRandMaximum - 1; 143 } 144 for (int channel = 0; channel < 4; ++channel) { 145 for (int i = 0; i < kBlockSize; ++i) { 146 fLatticeSelector[i] = i; 147 fNoise[channel][i][0] = (random() % (2 * kBlockSize)); 148 fNoise[channel][i][1] = (random() % (2 * kBlockSize)); 149 } 150 } 151 for (int i = kBlockSize - 1; i > 0; --i) { 152 int k = fLatticeSelector[i]; 153 int j = random() % kBlockSize; 154 SkASSERT(j >= 0); 155 SkASSERT(j < kBlockSize); 156 fLatticeSelector[i] = fLatticeSelector[j]; 157 fLatticeSelector[j] = k; 158 } 159 160 // Perform the permutations now 161 { 162 // Copy noise data 163 uint16_t noise[4][kBlockSize][2]; 164 for (int i = 0; i < kBlockSize; ++i) { 165 for (int channel = 0; channel < 4; ++channel) { 166 for (int j = 0; j < 2; ++j) { 167 noise[channel][i][j] = fNoise[channel][i][j]; 168 } 169 } 170 } 171 // Do permutations on noise data 172 for (int i = 0; i < kBlockSize; ++i) { 173 for (int channel = 0; channel < 4; ++channel) { 174 for (int j = 0; j < 2; ++j) { 175 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j]; 176 } 177 } 178 } 179 } 180 181 // Half of the largest possible value for 16 bit unsigned int 182 static const SkScalar gHalfMax16bits = 32767.5f; 183 184 // Compute gradients from permutated noise data 185 for (int channel = 0; channel < 4; ++channel) { 186 for (int i = 0; i < kBlockSize; ++i) { 187 fGradient[channel][i] = SkPoint::Make( 188 (fNoise[channel][i][0] - kBlockSize) * gInvBlockSizef, 189 (fNoise[channel][i][1] - kBlockSize) * gInvBlockSizef); 190 fGradient[channel][i].normalize(); 191 // Put the normalized gradient back into the noise data 192 fNoise[channel][i][0] = SkScalarRoundToInt( 193 (fGradient[channel][i].fX + 1) * gHalfMax16bits); 194 fNoise[channel][i][1] = SkScalarRoundToInt( 195 (fGradient[channel][i].fY + 1) * gHalfMax16bits); 196 } 197 } 198 } 199 200 // Only called once. Could be part of the constructor. 201 void stitch() { 202 SkScalar tileWidth = SkIntToScalar(fTileSize.width()); 203 SkScalar tileHeight = SkIntToScalar(fTileSize.height()); 204 SkASSERT(tileWidth > 0 && tileHeight > 0); 205 // When stitching tiled turbulence, the frequencies must be adjusted 206 // so that the tile borders will be continuous. 207 if (fBaseFrequency.fX) { 208 SkScalar lowFrequencx = 209 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 210 SkScalar highFrequencx = 211 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth; 212 // BaseFrequency should be non-negative according to the standard. 213 if (fBaseFrequency.fX / lowFrequencx < highFrequencx / fBaseFrequency.fX) { 214 fBaseFrequency.fX = lowFrequencx; 215 } else { 216 fBaseFrequency.fX = highFrequencx; 217 } 218 } 219 if (fBaseFrequency.fY) { 220 SkScalar lowFrequency = 221 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 222 SkScalar highFrequency = 223 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight; 224 if (fBaseFrequency.fY / lowFrequency < highFrequency / fBaseFrequency.fY) { 225 fBaseFrequency.fY = lowFrequency; 226 } else { 227 fBaseFrequency.fY = highFrequency; 228 } 229 } 230 // Set up TurbulenceInitial stitch values. 231 fStitchDataInit.fWidth = 232 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX); 233 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth; 234 fStitchDataInit.fHeight = 235 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); 236 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; 237 } 238 239public: 240 241#if SK_SUPPORT_GPU 242 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; } 243 244 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } 245#endif 246}; 247 248sk_sp<SkShader> SkPerlinNoiseShader::MakeFractalNoise(SkScalar baseFrequencyX, 249 SkScalar baseFrequencyY, 250 int numOctaves, SkScalar seed, 251 const SkISize* tileSize) { 252 return sk_sp<SkShader>(new SkPerlinNoiseShader(kFractalNoise_Type, baseFrequencyX, 253 baseFrequencyY, numOctaves, 254 seed, tileSize)); 255} 256 257sk_sp<SkShader> SkPerlinNoiseShader::MakeTurbulence(SkScalar baseFrequencyX, 258 SkScalar baseFrequencyY, 259 int numOctaves, SkScalar seed, 260 const SkISize* tileSize) { 261 return sk_sp<SkShader>(new SkPerlinNoiseShader(kTurbulence_Type, baseFrequencyX, baseFrequencyY, 262 numOctaves, seed, tileSize)); 263} 264 265SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, 266 SkScalar baseFrequencyX, 267 SkScalar baseFrequencyY, 268 int numOctaves, 269 SkScalar seed, 270 const SkISize* tileSize) 271 : fType(type) 272 , fBaseFrequencyX(baseFrequencyX) 273 , fBaseFrequencyY(baseFrequencyY) 274 , fNumOctaves(SkTPin<int>(numOctaves, 0, 255)) // [0,255] octaves allowed 275 , fSeed(seed) 276 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize) 277 , fStitchTiles(!fTileSize.isEmpty()) 278{ 279 SkASSERT(fNumOctaves >= 0 && fNumOctaves < 256); 280} 281 282SkPerlinNoiseShader::~SkPerlinNoiseShader() { 283} 284 285sk_sp<SkFlattenable> SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) { 286 Type type = (Type)buffer.readInt(); 287 SkScalar freqX = buffer.readScalar(); 288 SkScalar freqY = buffer.readScalar(); 289 int octaves = buffer.readInt(); 290 SkScalar seed = buffer.readScalar(); 291 SkISize tileSize; 292 tileSize.fWidth = buffer.readInt(); 293 tileSize.fHeight = buffer.readInt(); 294 295 switch (type) { 296 case kFractalNoise_Type: 297 return SkPerlinNoiseShader::MakeFractalNoise(freqX, freqY, octaves, seed, 298 &tileSize); 299 case kTurbulence_Type: 300 return SkPerlinNoiseShader::MakeTurbulence(freqX, freqY, octaves, seed, 301 &tileSize); 302 default: 303 return nullptr; 304 } 305} 306 307void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { 308 buffer.writeInt((int) fType); 309 buffer.writeScalar(fBaseFrequencyX); 310 buffer.writeScalar(fBaseFrequencyY); 311 buffer.writeInt(fNumOctaves); 312 buffer.writeScalar(fSeed); 313 buffer.writeInt(fTileSize.fWidth); 314 buffer.writeInt(fTileSize.fHeight); 315} 316 317SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( 318 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { 319 struct Noise { 320 int noisePositionIntegerValue; 321 int nextNoisePositionIntegerValue; 322 SkScalar noisePositionFractionValue; 323 Noise(SkScalar component) 324 { 325 SkScalar position = component + kPerlinNoise; 326 noisePositionIntegerValue = SkScalarFloorToInt(position); 327 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); 328 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; 329 } 330 }; 331 Noise noiseX(noiseVector.x()); 332 Noise noiseY(noiseVector.y()); 333 SkScalar u, v; 334 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 335 // If stitching, adjust lattice points accordingly. 336 if (perlinNoiseShader.fStitchTiles) { 337 noiseX.noisePositionIntegerValue = 338 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 339 noiseY.noisePositionIntegerValue = 340 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 341 noiseX.nextNoisePositionIntegerValue = 342 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); 343 noiseY.nextNoisePositionIntegerValue = 344 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); 345 } 346 noiseX.noisePositionIntegerValue &= kBlockMask; 347 noiseY.noisePositionIntegerValue &= kBlockMask; 348 noiseX.nextNoisePositionIntegerValue &= kBlockMask; 349 noiseY.nextNoisePositionIntegerValue &= kBlockMask; 350 int i = 351 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue]; 352 int j = 353 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; 354 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; 355 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; 356 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 357 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; 358 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); 359 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); 360 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement 361 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, 362 noiseY.noisePositionFractionValue); // Offset (0,0) 363 u = fPaintingData->fGradient[channel][b00].dot(fractionValue); 364 fractionValue.fX -= SK_Scalar1; // Offset (-1,0) 365 v = fPaintingData->fGradient[channel][b10].dot(fractionValue); 366 SkScalar a = SkScalarInterp(u, v, sx); 367 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) 368 v = fPaintingData->fGradient[channel][b11].dot(fractionValue); 369 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) 370 u = fPaintingData->fGradient[channel][b01].dot(fractionValue); 371 SkScalar b = SkScalarInterp(u, v, sx); 372 return SkScalarInterp(a, b, sy); 373} 374 375SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( 376 int channel, StitchData& stitchData, const SkPoint& point) const { 377 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); 378 if (perlinNoiseShader.fStitchTiles) { 379 // Set up TurbulenceInitial stitch values. 380 stitchData = fPaintingData->fStitchDataInit; 381 } 382 SkScalar turbulenceFunctionResult = 0; 383 SkPoint noiseVector(SkPoint::Make(point.x() * fPaintingData->fBaseFrequency.fX, 384 point.y() * fPaintingData->fBaseFrequency.fY)); 385 SkScalar ratio = SK_Scalar1; 386 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { 387 SkScalar noise = noise2D(channel, stitchData, noiseVector); 388 SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ? 389 noise : SkScalarAbs(noise); 390 turbulenceFunctionResult += numer / ratio; 391 noiseVector.fX *= 2; 392 noiseVector.fY *= 2; 393 ratio *= 2; 394 if (perlinNoiseShader.fStitchTiles) { 395 // Update stitch values 396 stitchData.fWidth *= 2; 397 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; 398 stitchData.fHeight *= 2; 399 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; 400 } 401 } 402 403 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 404 // by fractalNoise and (turbulenceFunctionResult) by turbulence. 405 if (perlinNoiseShader.fType == kFractalNoise_Type) { 406 turbulenceFunctionResult = turbulenceFunctionResult * SK_ScalarHalf + SK_ScalarHalf; 407 } 408 409 if (channel == 3) { // Scale alpha by paint value 410 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; 411 } 412 413 // Clamp result 414 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); 415} 416 417SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( 418 const SkPoint& point, StitchData& stitchData) const { 419 SkPoint newPoint; 420 fMatrix.mapPoints(&newPoint, &point, 1); 421 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); 422 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); 423 424 U8CPU rgba[4]; 425 for (int channel = 3; channel >= 0; --channel) { 426 rgba[channel] = SkScalarFloorToInt(255 * 427 calculateTurbulenceValueForPoint(channel, stitchData, newPoint)); 428 } 429 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); 430} 431 432SkShader::Context* SkPerlinNoiseShader::onMakeContext( 433 const ContextRec& rec, SkArenaAlloc* alloc) const { 434 return alloc->make<PerlinNoiseShaderContext>(*this, rec); 435} 436 437SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( 438 const SkPerlinNoiseShader& shader, const ContextRec& rec) 439 : INHERITED(shader, rec) 440{ 441 SkMatrix newMatrix = SkMatrix::Concat(*rec.fMatrix, shader.getLocalMatrix()); 442 if (rec.fLocalMatrix) { 443 newMatrix.preConcat(*rec.fLocalMatrix); 444 } 445 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise 446 // (as opposed to 0 based, usually). The same adjustment is in the setData() function. 447 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1); 448 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, 449 shader.fBaseFrequencyY, newMatrix); 450} 451 452SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { delete fPaintingData; } 453 454void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( 455 int x, int y, SkPMColor result[], int count) { 456 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); 457 StitchData stitchData; 458 for (int i = 0; i < count; ++i) { 459 result[i] = shade(point, stitchData); 460 point.fX += SK_Scalar1; 461 } 462} 463 464///////////////////////////////////////////////////////////////////// 465 466#if SK_SUPPORT_GPU 467 468class GrGLPerlinNoise : public GrGLSLFragmentProcessor { 469public: 470 void emitCode(EmitArgs&) override; 471 472 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*); 473 474protected: 475 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 476 477private: 478 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; 479 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; 480 481 typedef GrGLSLFragmentProcessor INHERITED; 482}; 483 484///////////////////////////////////////////////////////////////////// 485 486class GrPerlinNoiseEffect : public GrFragmentProcessor { 487public: 488 static sk_sp<GrFragmentProcessor> Make(GrResourceProvider* resourceProvider, 489 SkPerlinNoiseShader::Type type, 490 int numOctaves, bool stitchTiles, 491 SkPerlinNoiseShader::PaintingData* paintingData, 492 sk_sp<GrTextureProxy> permutationsProxy, 493 sk_sp<GrTextureProxy> noiseProxy, 494 const SkMatrix& matrix) { 495 return sk_sp<GrFragmentProcessor>( 496 new GrPerlinNoiseEffect(resourceProvider, type, numOctaves, stitchTiles, paintingData, 497 std::move(permutationsProxy), std::move(noiseProxy), matrix)); 498 } 499 500 ~GrPerlinNoiseEffect() override { delete fPaintingData; } 501 502 const char* name() const override { return "PerlinNoise"; } 503 504 const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; } 505 506 SkPerlinNoiseShader::Type type() const { return fType; } 507 bool stitchTiles() const { return fStitchTiles; } 508 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; } 509 int numOctaves() const { return fNumOctaves; } 510 511private: 512 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 513 return new GrGLPerlinNoise; 514 } 515 516 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps, 517 GrProcessorKeyBuilder* b) const override { 518 GrGLPerlinNoise::GenKey(*this, caps, b); 519 } 520 521 bool onIsEqual(const GrFragmentProcessor& sBase) const override { 522 const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); 523 return fType == s.fType && 524 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency && 525 fNumOctaves == s.fNumOctaves && 526 fStitchTiles == s.fStitchTiles && 527 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit; 528 } 529 530 GrPerlinNoiseEffect(GrResourceProvider* resourceProvider, 531 SkPerlinNoiseShader::Type type, int numOctaves, bool stitchTiles, 532 SkPerlinNoiseShader::PaintingData* paintingData, 533 sk_sp<GrTextureProxy> permutationsProxy, sk_sp<GrTextureProxy> noiseProxy, 534 const SkMatrix& matrix) 535 : INHERITED(kNone_OptimizationFlags) 536 , fType(type) 537 , fCoordTransform(matrix) 538 , fNumOctaves(numOctaves) 539 , fStitchTiles(stitchTiles) 540 , fPermutationsSampler(resourceProvider, std::move(permutationsProxy)) 541 , fNoiseSampler(resourceProvider, std::move(noiseProxy)) 542 , fPaintingData(paintingData) { 543 this->initClassID<GrPerlinNoiseEffect>(); 544 this->addTextureSampler(&fPermutationsSampler); 545 this->addTextureSampler(&fNoiseSampler); 546 this->addCoordTransform(&fCoordTransform); 547 } 548 549 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 550 551 SkPerlinNoiseShader::Type fType; 552 GrCoordTransform fCoordTransform; 553 int fNumOctaves; 554 bool fStitchTiles; 555 TextureSampler fPermutationsSampler; 556 TextureSampler fNoiseSampler; 557 SkPerlinNoiseShader::PaintingData *fPaintingData; 558 559private: 560 typedef GrFragmentProcessor INHERITED; 561}; 562 563///////////////////////////////////////////////////////////////////// 564GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect); 565 566#if GR_TEST_UTILS 567sk_sp<GrFragmentProcessor> GrPerlinNoiseEffect::TestCreate(GrProcessorTestData* d) { 568 int numOctaves = d->fRandom->nextRangeU(2, 10); 569 bool stitchTiles = d->fRandom->nextBool(); 570 SkScalar seed = SkIntToScalar(d->fRandom->nextU()); 571 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096), 572 d->fRandom->nextRangeU(4, 4096)); 573 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, 574 0.99f); 575 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, 576 0.99f); 577 578 sk_sp<SkShader> shader(d->fRandom->nextBool() ? 579 SkPerlinNoiseShader::MakeFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed, 580 stitchTiles ? &tileSize : nullptr) : 581 SkPerlinNoiseShader::MakeTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed, 582 stitchTiles ? &tileSize : nullptr)); 583 584 GrTest::TestAsFPArgs asFPArgs(d); 585 return shader->asFragmentProcessor(asFPArgs.args()); 586} 587#endif 588 589void GrGLPerlinNoise::emitCode(EmitArgs& args) { 590 const GrPerlinNoiseEffect& pne = args.fFp.cast<GrPerlinNoiseEffect>(); 591 592 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 593 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler; 594 SkString vCoords = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]); 595 596 fBaseFrequencyUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 597 kVec2f_GrSLType, kDefault_GrSLPrecision, 598 "baseFrequency"); 599 const char* baseFrequencyUni = uniformHandler->getUniformCStr(fBaseFrequencyUni); 600 601 const char* stitchDataUni = nullptr; 602 if (pne.stitchTiles()) { 603 fStitchDataUni = uniformHandler->addUniform(kFragment_GrShaderFlag, 604 kVec2f_GrSLType, kDefault_GrSLPrecision, 605 "stitchData"); 606 stitchDataUni = uniformHandler->getUniformCStr(fStitchDataUni); 607 } 608 609 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8 610 const char* chanCoordR = "0.125"; 611 const char* chanCoordG = "0.375"; 612 const char* chanCoordB = "0.625"; 613 const char* chanCoordA = "0.875"; 614 const char* chanCoord = "chanCoord"; 615 const char* stitchData = "stitchData"; 616 const char* ratio = "ratio"; 617 const char* noiseVec = "noiseVec"; 618 const char* noiseSmooth = "noiseSmooth"; 619 const char* floorVal = "floorVal"; 620 const char* fractVal = "fractVal"; 621 const char* uv = "uv"; 622 const char* ab = "ab"; 623 const char* latticeIdx = "latticeIdx"; 624 const char* bcoords = "bcoords"; 625 const char* lattice = "lattice"; 626 const char* inc8bit = "0.00390625"; // 1.0 / 256.0 627 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a 628 // [-1,1] vector and perform a dot product between that vector and the provided vector. 629 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);"; 630 631 // Add noise function 632 static const GrShaderVar gPerlinNoiseArgs[] = { 633 GrShaderVar(chanCoord, kFloat_GrSLType), 634 GrShaderVar(noiseVec, kVec2f_GrSLType) 635 }; 636 637 static const GrShaderVar gPerlinNoiseStitchArgs[] = { 638 GrShaderVar(chanCoord, kFloat_GrSLType), 639 GrShaderVar(noiseVec, kVec2f_GrSLType), 640 GrShaderVar(stitchData, kVec2f_GrSLType) 641 }; 642 643 SkString noiseCode; 644 645 noiseCode.appendf("\tvec4 %s;\n", floorVal); 646 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec); 647 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal); 648 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec); 649 650 // smooth curve : t * t * (3 - 2 * t) 651 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);", 652 noiseSmooth, fractVal, fractVal, fractVal); 653 654 // Adjust frequencies if we're stitching tiles 655 if (pne.stitchTiles()) { 656 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }", 657 floorVal, stitchData, floorVal, stitchData); 658 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", 659 floorVal, stitchData, floorVal, stitchData); 660 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }", 661 floorVal, stitchData, floorVal, stitchData); 662 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }", 663 floorVal, stitchData, floorVal, stitchData); 664 } 665 666 // Get texture coordinates and normalize 667 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n", 668 floorVal, floorVal); 669 670 // Get permutation for x 671 { 672 SkString xCoords(""); 673 xCoords.appendf("vec2(%s.x, 0.5)", floorVal); 674 675 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); 676 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), 677 kVec2f_GrSLType); 678 noiseCode.append(".r;"); 679 } 680 681 // Get permutation for x + 1 682 { 683 SkString xCoords(""); 684 xCoords.appendf("vec2(%s.z, 0.5)", floorVal); 685 686 noiseCode.appendf("\n\t%s.y = ", latticeIdx); 687 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[0], xCoords.c_str(), 688 kVec2f_GrSLType); 689 noiseCode.append(".r;"); 690 } 691 692#if defined(SK_BUILD_FOR_ANDROID) 693 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). 694 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit 695 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 696 // (or 0.484368 here). The following rounding operation prevents these precision issues from 697 // affecting the result of the noise by making sure that we only have multiples of 1/255. 698 // (Note that 1/255 is about 0.003921569, which is the value used here). 699 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", 700 latticeIdx, latticeIdx); 701#endif 702 703 // Get (x,y) coordinates with the permutated x 704 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal); 705 706 noiseCode.appendf("\n\n\tvec2 %s;", uv); 707 // Compute u, at offset (0,0) 708 { 709 SkString latticeCoords(""); 710 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord); 711 noiseCode.appendf("\n\tvec4 %s = ", lattice); 712 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 713 kVec2f_GrSLType); 714 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 715 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 716 } 717 718 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); 719 // Compute v, at offset (-1,0) 720 { 721 SkString latticeCoords(""); 722 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); 723 noiseCode.append("\n\tlattice = "); 724 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 725 kVec2f_GrSLType); 726 noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 727 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 728 } 729 730 // Compute 'a' as a linear interpolation of 'u' and 'v' 731 noiseCode.appendf("\n\tvec2 %s;", ab); 732 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 733 734 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); 735 // Compute v, at offset (-1,-1) 736 { 737 SkString latticeCoords(""); 738 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); 739 noiseCode.append("\n\tlattice = "); 740 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 741 kVec2f_GrSLType); 742 noiseCode.appendf(".bgra;\n\t%s.y = ", uv); 743 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 744 } 745 746 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); 747 // Compute u, at offset (0,-1) 748 { 749 SkString latticeCoords(""); 750 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); 751 noiseCode.append("\n\tlattice = "); 752 fragBuilder->appendTextureLookup(&noiseCode, args.fTexSamplers[1], latticeCoords.c_str(), 753 kVec2f_GrSLType); 754 noiseCode.appendf(".bgra;\n\t%s.x = ", uv); 755 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); 756 } 757 758 // Compute 'b' as a linear interpolation of 'u' and 'v' 759 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); 760 // Compute the noise as a linear interpolation of 'a' and 'b' 761 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); 762 763 SkString noiseFuncName; 764 if (pne.stitchTiles()) { 765 fragBuilder->emitFunction(kFloat_GrSLType, 766 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), 767 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); 768 } else { 769 fragBuilder->emitFunction(kFloat_GrSLType, 770 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), 771 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); 772 } 773 774 // There are rounding errors if the floor operation is not performed here 775 fragBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", 776 noiseVec, vCoords.c_str(), baseFrequencyUni); 777 778 // Clear the color accumulator 779 fragBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", args.fOutputColor); 780 781 if (pne.stitchTiles()) { 782 // Set up TurbulenceInitial stitch values. 783 fragBuilder->codeAppendf("vec2 %s = %s;", stitchData, stitchDataUni); 784 } 785 786 fragBuilder->codeAppendf("float %s = 1.0;", ratio); 787 788 // Loop over all octaves 789 fragBuilder->codeAppendf("for (int octave = 0; octave < %d; ++octave) {", pne.numOctaves()); 790 791 fragBuilder->codeAppendf("%s += ", args.fOutputColor); 792 if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) { 793 fragBuilder->codeAppend("abs("); 794 } 795 if (pne.stitchTiles()) { 796 fragBuilder->codeAppendf( 797 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," 798 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", 799 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, 800 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, 801 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, 802 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); 803 } else { 804 fragBuilder->codeAppendf( 805 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," 806 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", 807 noiseFuncName.c_str(), chanCoordR, noiseVec, 808 noiseFuncName.c_str(), chanCoordG, noiseVec, 809 noiseFuncName.c_str(), chanCoordB, noiseVec, 810 noiseFuncName.c_str(), chanCoordA, noiseVec); 811 } 812 if (pne.type() != SkPerlinNoiseShader::kFractalNoise_Type) { 813 fragBuilder->codeAppendf(")"); // end of "abs(" 814 } 815 fragBuilder->codeAppendf(" * %s;", ratio); 816 817 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); 818 fragBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); 819 820 if (pne.stitchTiles()) { 821 fragBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); 822 } 823 fragBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves 824 825 if (pne.type() == SkPerlinNoiseShader::kFractalNoise_Type) { 826 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 827 // by fractalNoise and (turbulenceFunctionResult) by turbulence. 828 fragBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", 829 args.fOutputColor,args.fOutputColor); 830 } 831 832 // Clamp values 833 fragBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.fOutputColor); 834 835 // Pre-multiply the result 836 fragBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", 837 args.fOutputColor, args.fOutputColor, 838 args.fOutputColor, args.fOutputColor); 839} 840 841void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrShaderCaps&, 842 GrProcessorKeyBuilder* b) { 843 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 844 845 uint32_t key = turbulence.numOctaves(); 846 847 key = key << 3; // Make room for next 3 bits 848 849 switch (turbulence.type()) { 850 case SkPerlinNoiseShader::kFractalNoise_Type: 851 key |= 0x1; 852 break; 853 case SkPerlinNoiseShader::kTurbulence_Type: 854 key |= 0x2; 855 break; 856 default: 857 // leave key at 0 858 break; 859 } 860 861 if (turbulence.stitchTiles()) { 862 key |= 0x4; // Flip the 3rd bit if tile stitching is on 863 } 864 865 b->add32(key); 866} 867 868void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman, 869 const GrProcessor& processor) { 870 INHERITED::onSetData(pdman, processor); 871 872 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(); 873 874 const SkVector& baseFrequency = turbulence.baseFrequency(); 875 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); 876 877 if (turbulence.stitchTiles()) { 878 const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData(); 879 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), 880 SkIntToScalar(stitchData.fHeight)); 881 } 882} 883 884///////////////////////////////////////////////////////////////////// 885sk_sp<GrFragmentProcessor> SkPerlinNoiseShader::asFragmentProcessor(const AsFPArgs& args) const { 886 SkASSERT(args.fContext); 887 888 SkMatrix localMatrix = this->getLocalMatrix(); 889 if (args.fLocalMatrix) { 890 localMatrix.preConcat(*args.fLocalMatrix); 891 } 892 893 SkMatrix matrix = *args.fViewMatrix; 894 matrix.preConcat(localMatrix); 895 896 if (0 == fNumOctaves) { 897 if (kFractalNoise_Type == fType) { 898 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) 899 // TODO: Either treat the output of this shader as sRGB or allow client to specify a 900 // color space of the noise. Either way, this case (and the GLSL) need to convert to 901 // the destination. 902 sk_sp<GrFragmentProcessor> inner( 903 GrConstColorProcessor::Make(GrColor4f::FromGrColor(0x80404040), 904 GrConstColorProcessor::kModulateRGBA_InputMode)); 905 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); 906 } 907 // Emit zero. 908 return GrConstColorProcessor::Make(GrColor4f::TransparentBlack(), 909 GrConstColorProcessor::kIgnore_InputMode); 910 } 911 912 // Either we don't stitch tiles, either we have a valid tile size 913 SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); 914 915 SkPerlinNoiseShader::PaintingData* paintingData = 916 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix); 917 sk_sp<GrTextureProxy> permutationsProxy(GrMakeCachedBitmapProxy( 918 args.fContext->resourceProvider(), 919 paintingData->getPermutationsBitmap())); 920 sk_sp<GrTextureProxy> noiseProxy(GrMakeCachedBitmapProxy(args.fContext->resourceProvider(), 921 paintingData->getNoiseBitmap())); 922 923 SkMatrix m = *args.fViewMatrix; 924 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); 925 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); 926 if (permutationsProxy && noiseProxy) { 927 sk_sp<GrFragmentProcessor> inner( 928 GrPerlinNoiseEffect::Make(args.fContext->resourceProvider(), 929 fType, 930 fNumOctaves, 931 fStitchTiles, 932 paintingData, 933 std::move(permutationsProxy), 934 std::move(noiseProxy), 935 m)); 936 return GrFragmentProcessor::MulOutputByInputAlpha(std::move(inner)); 937 } 938 delete paintingData; 939 return nullptr; 940} 941 942#endif 943 944#ifndef SK_IGNORE_TO_STRING 945void SkPerlinNoiseShader::toString(SkString* str) const { 946 str->append("SkPerlinNoiseShader: ("); 947 948 str->append("type: "); 949 switch (fType) { 950 case kFractalNoise_Type: 951 str->append("\"fractal noise\""); 952 break; 953 case kTurbulence_Type: 954 str->append("\"turbulence\""); 955 break; 956 default: 957 str->append("\"unknown\""); 958 break; 959 } 960 str->append(" base frequency: ("); 961 str->appendScalar(fBaseFrequencyX); 962 str->append(", "); 963 str->appendScalar(fBaseFrequencyY); 964 str->append(") number of octaves: "); 965 str->appendS32(fNumOctaves); 966 str->append(" seed: "); 967 str->appendScalar(fSeed); 968 str->append(" stitch tiles: "); 969 str->append(fStitchTiles ? "true " : "false "); 970 971 this->INHERITED::toString(str); 972 973 str->append(")"); 974} 975#endif 976