| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkDither.h" | 8 #include "SkDither.h" |
| 9 #include "SkPerlinNoiseShader.h" | 9 #include "SkPerlinNoiseShader2.h" |
| 10 #include "SkColorFilter.h" | 10 #include "SkColorFilter.h" |
| 11 #include "SkReadBuffer.h" | 11 #include "SkReadBuffer.h" |
| 12 #include "SkWriteBuffer.h" | 12 #include "SkWriteBuffer.h" |
| 13 #include "SkShader.h" | 13 #include "SkShader.h" |
| 14 #include "SkUnPreMultiply.h" | 14 #include "SkUnPreMultiply.h" |
| 15 #include "SkString.h" | 15 #include "SkString.h" |
| 16 | 16 |
| 17 #if SK_SUPPORT_GPU | 17 #if SK_SUPPORT_GPU |
| 18 #include "GrContext.h" | 18 #include "GrContext.h" |
| 19 #include "GrCoordTransform.h" | 19 #include "GrCoordTransform.h" |
| 20 #include "GrInvariantOutput.h" | 20 #include "GrInvariantOutput.h" |
| 21 #include "SkGr.h" | 21 #include "SkGr.h" |
| 22 #include "effects/GrConstColorProcessor.h" | 22 #include "effects/GrConstColorProcessor.h" |
| 23 #include "gl/GrGLFragmentProcessor.h" | 23 #include "gl/GrGLFragmentProcessor.h" |
| 24 #include "gl/builders/GrGLProgramBuilder.h" | 24 #include "gl/builders/GrGLProgramBuilder.h" |
| 25 #include "glsl/GrGLSLProgramDataManager.h" | 25 #include "glsl/GrGLSLProgramDataManager.h" |
| 26 #endif | 26 #endif |
| 27 | 27 |
| 28 static const int kBlockSize = 256; | 28 static const int kBlockSize = 256; |
| 29 static const int kBlockMask = kBlockSize - 1; | 29 static const int kBlockMask = kBlockSize - 1; |
| 30 static const int kPerlinNoise = 4096; | 30 static const int kPerlinNoise = 4096; |
| 31 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1 | 31 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1 |
| 32 | 32 |
| 33 static uint8_t improved_noise_permutations[] = { |
| 34 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 2
25, 140, 36, 103, |
| 35 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 2
34, 75, 0, 26, |
| 36 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 1
49, 56, 87, 174, |
| 37 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
77, 146, 158, 231, |
| 38 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245,
40, 244, 102, 143, |
| 39 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89,
18, 169, 200, 196, |
| 40 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 2
17, 226, 250, 124, |
| 41 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227,
47, 16, 58, 17, |
| 42 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
70, 221, 153, 101, |
| 43 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 2
24, 232, 178, 185, |
| 44 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 1
79, 162, 241, 81, |
| 45 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 1
84, 84, 204, 176, |
| 46 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67,
29, 24, 72, 243, |
| 47 141, 128, 195, 78, 66, 215, 61, 156, 180, |
| 48 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 2
25, 140, 36, 103, |
| 49 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 2
34, 75, 0, 26, |
| 50 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 1
49, 56, 87, 174, |
| 51 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
77, 146, 158, 231, |
| 52 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245,
40, 244, 102, 143, |
| 53 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89,
18, 169, 200, 196, |
| 54 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 2
17, 226, 250, 124, |
| 55 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227,
47, 16, 58, 17, |
| 56 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163,
70, 221, 153, 101, |
| 57 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 2
24, 232, 178, 185, |
| 58 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 1
79, 162, 241, 81, |
| 59 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 1
84, 84, 204, 176, |
| 60 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67,
29, 24, 72, 243, |
| 61 141, 128, 195, 78, 66, 215, 61, 156, 180 |
| 62 }; |
| 63 |
| 33 namespace { | 64 namespace { |
| 34 | 65 |
| 35 // noiseValue is the color component's value (or color) | 66 // noiseValue is the color component's value (or color) |
| 36 // limitValue is the maximum perlin noise array index value allowed | 67 // limitValue is the maximum perlin noise array index value allowed |
| 37 // newValue is the current noise dimension (either width or height) | 68 // newValue is the current noise dimension (either width or height) |
| 38 inline int checkNoise(int noiseValue, int limitValue, int newValue) { | 69 inline int checkNoise(int noiseValue, int limitValue, int newValue) { |
| 39 // If the noise value would bring us out of bounds of the current noise arra
y while we are | 70 // If the noise value would bring us out of bounds of the current noise arra
y while we are |
| 40 // stiching noise tiles together, wrap the noise around the current dimensio
n of the noise to | 71 // stiching noise tiles together, wrap the noise around the current dimensio
n of the noise to |
| 41 // stay within the array bounds in a continuous fashion (so that tiling line
s are not visible) | 72 // stay within the array bounds in a continuous fashion (so that tiling line
s are not visible) |
| 42 if (noiseValue >= limitValue) { | 73 if (noiseValue >= limitValue) { |
| 43 noiseValue -= newValue; | 74 noiseValue -= newValue; |
| 44 } | 75 } |
| 45 return noiseValue; | 76 return noiseValue; |
| 46 } | 77 } |
| 47 | 78 |
| 48 inline SkScalar smoothCurve(SkScalar t) { | 79 inline SkScalar smoothCurve(SkScalar t) { |
| 49 static const SkScalar SK_Scalar3 = 3.0f; | 80 static const SkScalar SK_Scalar3 = 3.0f; |
| 50 | 81 |
| 51 // returns t * t * (3 - 2 * t) | 82 // returns t * t * (3 - 2 * t) |
| 52 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t); | 83 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t); |
| 53 } | 84 } |
| 54 | 85 |
| 55 } // end namespace | 86 } // end namespace |
| 56 | 87 |
| 57 struct SkPerlinNoiseShader::StitchData { | 88 struct SkPerlinNoiseShader2::StitchData { |
| 58 StitchData() | 89 StitchData() |
| 59 : fWidth(0) | 90 : fWidth(0) |
| 60 , fWrapX(0) | 91 , fWrapX(0) |
| 61 , fHeight(0) | 92 , fHeight(0) |
| 62 , fWrapY(0) | 93 , fWrapY(0) |
| 63 {} | 94 {} |
| 64 | 95 |
| 65 bool operator==(const StitchData& other) const { | 96 bool operator==(const StitchData& other) const { |
| 66 return fWidth == other.fWidth && | 97 return fWidth == other.fWidth && |
| 67 fWrapX == other.fWrapX && | 98 fWrapX == other.fWrapX && |
| 68 fHeight == other.fHeight && | 99 fHeight == other.fHeight && |
| 69 fWrapY == other.fWrapY; | 100 fWrapY == other.fWrapY; |
| 70 } | 101 } |
| 71 | 102 |
| 72 int fWidth; // How much to subtract to wrap for stitching. | 103 int fWidth; // How much to subtract to wrap for stitching. |
| 73 int fWrapX; // Minimum value to wrap. | 104 int fWrapX; // Minimum value to wrap. |
| 74 int fHeight; | 105 int fHeight; |
| 75 int fWrapY; | 106 int fWrapY; |
| 76 }; | 107 }; |
| 77 | 108 |
| 78 struct SkPerlinNoiseShader::PaintingData { | 109 struct SkPerlinNoiseShader2::PaintingData { |
| 79 PaintingData(const SkISize& tileSize, SkScalar seed, | 110 PaintingData(const SkISize& tileSize, SkScalar seed, |
| 80 SkScalar baseFrequencyX, SkScalar baseFrequencyY, | 111 SkScalar baseFrequencyX, SkScalar baseFrequencyY, |
| 81 const SkMatrix& matrix) | 112 const SkMatrix& matrix) |
| 82 { | 113 { |
| 83 SkVector vec[2] = { | 114 SkVector vec[2] = { |
| 84 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY)
}, | 115 { SkScalarInvert(baseFrequencyX), SkScalarInvert(baseFrequencyY)
}, |
| 85 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight)
}, | 116 { SkIntToScalar(tileSize.fWidth), SkIntToScalar(tileSize.fHeight)
}, |
| 86 }; | 117 }; |
| 87 matrix.mapVectors(vec, 2); | 118 matrix.mapVectors(vec, 2); |
| 88 | 119 |
| 89 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY))
; | 120 fBaseFrequency.set(SkScalarInvert(vec[0].fX), SkScalarInvert(vec[0].fY))
; |
| 90 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].f
Y)); | 121 fTileSize.set(SkScalarRoundToInt(vec[1].fX), SkScalarRoundToInt(vec[1].f
Y)); |
| 91 this->init(seed); | 122 this->init(seed); |
| 92 if (!fTileSize.isEmpty()) { | 123 if (!fTileSize.isEmpty()) { |
| 93 this->stitch(); | 124 this->stitch(); |
| 94 } | 125 } |
| 95 | 126 |
| 96 #if SK_SUPPORT_GPU | 127 #if SK_SUPPORT_GPU |
| 97 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); | 128 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1)); |
| 98 fPermutationsBitmap.setPixels(fLatticeSelector); | 129 fPermutationsBitmap.setPixels(fLatticeSelector); |
| 99 | 130 |
| 100 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); | 131 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4)); |
| 101 fNoiseBitmap.setPixels(fNoise[0][0]); | 132 fNoiseBitmap.setPixels(fNoise[0][0]); |
| 133 |
| 134 fImprovedPermutationsBitmap.setInfo(SkImageInfo::MakeA8(256, 1)); |
| 135 fImprovedPermutationsBitmap.setPixels(improved_noise_permutations); |
| 136 |
| 137 fGradientBitmap.setInfo(SkImageInfo::MakeN32Premul(16, 1)); |
| 138 static uint8_t gradients[] = { 2, 2, 1, 0, |
| 139 0, 2, 1, 0, |
| 140 2, 0, 1, 0, |
| 141 0, 0, 1, 0, |
| 142 2, 1, 2, 0, |
| 143 0, 1, 2, 0, |
| 144 2, 1, 0, 0, |
| 145 0, 1, 0, 0, |
| 146 1, 2, 2, 0, |
| 147 1, 0, 2, 0, |
| 148 1, 2, 0, 0, |
| 149 1, 0, 0, 0, |
| 150 2, 2, 1, 0, |
| 151 1, 0, 2, 0, |
| 152 0, 2, 1, 0, |
| 153 1, 0, 0, 0 }; |
| 154 fGradientBitmap.setPixels(gradients); |
| 102 #endif | 155 #endif |
| 103 } | 156 } |
| 104 | 157 |
| 105 int fSeed; | 158 int fSeed; |
| 106 uint8_t fLatticeSelector[kBlockSize]; | 159 uint8_t fLatticeSelector[kBlockSize]; |
| 107 uint16_t fNoise[4][kBlockSize][2]; | 160 uint16_t fNoise[4][kBlockSize][2]; |
| 108 SkPoint fGradient[4][kBlockSize]; | 161 SkPoint fGradient[4][kBlockSize]; |
| 109 SkISize fTileSize; | 162 SkISize fTileSize; |
| 110 SkVector fBaseFrequency; | 163 SkVector fBaseFrequency; |
| 111 StitchData fStitchDataInit; | 164 StitchData fStitchDataInit; |
| 112 | 165 |
| 113 private: | 166 private: |
| 114 | 167 |
| 115 #if SK_SUPPORT_GPU | 168 #if SK_SUPPORT_GPU |
| 116 SkBitmap fPermutationsBitmap; | 169 SkBitmap fPermutationsBitmap; |
| 117 SkBitmap fNoiseBitmap; | 170 SkBitmap fNoiseBitmap; |
| 171 SkBitmap fImprovedPermutationsBitmap; |
| 172 SkBitmap fGradientBitmap; |
| 118 #endif | 173 #endif |
| 119 | 174 |
| 120 inline int random() { | 175 inline int random() { |
| 121 static const int gRandAmplitude = 16807; // 7**5; primitive root of m | 176 static const int gRandAmplitude = 16807; // 7**5; primitive root of m |
| 122 static const int gRandQ = 127773; // m / a | 177 static const int gRandQ = 127773; // m / a |
| 123 static const int gRandR = 2836; // m % a | 178 static const int gRandR = 2836; // m % a |
| 124 | 179 |
| 125 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRand
Q); | 180 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRand
Q); |
| 126 if (result <= 0) | 181 if (result <= 0) |
| 127 result += kRandMaximum; | 182 result += kRandMaximum; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); | 294 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY); |
| 240 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; | 295 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight; |
| 241 } | 296 } |
| 242 | 297 |
| 243 public: | 298 public: |
| 244 | 299 |
| 245 #if SK_SUPPORT_GPU | 300 #if SK_SUPPORT_GPU |
| 246 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap;
} | 301 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap;
} |
| 247 | 302 |
| 248 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } | 303 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; } |
| 304 |
| 305 const SkBitmap& getImprovedPermutationsBitmap() const { return fImprovedPerm
utationsBitmap; } |
| 306 |
| 307 const SkBitmap& getGradientBitmap() const { return fGradientBitmap; } |
| 249 #endif | 308 #endif |
| 250 }; | 309 }; |
| 251 | 310 |
| 252 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkSca
lar baseFrequencyY, | 311 SkShader* SkPerlinNoiseShader2::CreateFractalNoise(SkScalar baseFrequencyX, SkSc
alar baseFrequencyY, |
| 253 int numOctaves, SkScalar seed, | 312 int numOctaves, SkScalar seed, |
| 254 const SkISize* tileSize) { | 313 const SkISize* tileSize) { |
| 255 return new SkPerlinNoiseShader(kFractalNoise_Type, baseFrequencyX, baseFrequ
encyY, numOctaves, | 314 return new SkPerlinNoiseShader2(kFractalNoise_Type, baseFrequencyX, baseFreq
uencyY, numOctaves, |
| 256 seed, tileSize); | 315 seed, tileSize); |
| 257 } | 316 } |
| 258 | 317 |
| 259 SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScala
r baseFrequencyY, | 318 SkShader* SkPerlinNoiseShader2::CreateTurbulence(SkScalar baseFrequencyX, SkScal
ar baseFrequencyY, |
| 260 int numOctaves, SkScalar seed, | 319 int numOctaves, SkScalar seed, |
| 261 const SkISize* tileSize) { | 320 const SkISize* tileSize) { |
| 262 return new SkPerlinNoiseShader(kTurbulence_Type, baseFrequencyX, baseFrequen
cyY, numOctaves, | 321 return new SkPerlinNoiseShader2(kTurbulence_Type, baseFrequencyX, baseFreque
ncyY, numOctaves, |
| 263 seed, tileSize); | 322 seed, tileSize); |
| 264 } | 323 } |
| 265 | 324 |
| 266 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type, | 325 SkShader* SkPerlinNoiseShader2::CreateImprovedNoise(SkScalar baseFrequencyX, SkS
calar baseFrequencyY, |
| 326 int numOctaves, SkScalar z)
{ |
| 327 return new SkPerlinNoiseShader2(kImprovedNoise_Type, baseFrequencyX, baseFre
quencyY, numOctaves, |
| 328 z, NULL); |
| 329 } |
| 330 |
| 331 SkPerlinNoiseShader2::SkPerlinNoiseShader2(SkPerlinNoiseShader2::Type type, |
| 267 SkScalar baseFrequencyX, | 332 SkScalar baseFrequencyX, |
| 268 SkScalar baseFrequencyY, | 333 SkScalar baseFrequencyY, |
| 269 int numOctaves, | 334 int numOctaves, |
| 270 SkScalar seed, | 335 SkScalar seed, |
| 271 const SkISize* tileSize) | 336 const SkISize* tileSize) |
| 272 : fType(type) | 337 : fType(type) |
| 273 , fBaseFrequencyX(baseFrequencyX) | 338 , fBaseFrequencyX(baseFrequencyX) |
| 274 , fBaseFrequencyY(baseFrequencyY) | 339 , fBaseFrequencyY(baseFrequencyY) |
| 275 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) | 340 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/) |
| 276 , fSeed(seed) | 341 , fSeed(seed) |
| 277 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize) | 342 , fTileSize(nullptr == tileSize ? SkISize::Make(0, 0) : *tileSize) |
| 278 , fStitchTiles(!fTileSize.isEmpty()) | 343 , fStitchTiles(!fTileSize.isEmpty()) |
| 279 { | 344 { |
| 280 SkASSERT(numOctaves >= 0 && numOctaves < 256); | 345 SkASSERT(numOctaves >= 0 && numOctaves < 256); |
| 281 } | 346 } |
| 282 | 347 |
| 283 SkPerlinNoiseShader::~SkPerlinNoiseShader() { | 348 SkPerlinNoiseShader2::~SkPerlinNoiseShader2() { |
| 284 } | 349 } |
| 285 | 350 |
| 286 SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) { | 351 SkFlattenable* SkPerlinNoiseShader2::CreateProc(SkReadBuffer& buffer) { |
| 287 Type type = (Type)buffer.readInt(); | 352 Type type = (Type)buffer.readInt(); |
| 288 SkScalar freqX = buffer.readScalar(); | 353 SkScalar freqX = buffer.readScalar(); |
| 289 SkScalar freqY = buffer.readScalar(); | 354 SkScalar freqY = buffer.readScalar(); |
| 290 int octaves = buffer.readInt(); | 355 int octaves = buffer.readInt(); |
| 291 SkScalar seed = buffer.readScalar(); | 356 SkScalar seed = buffer.readScalar(); |
| 292 SkISize tileSize; | 357 SkISize tileSize; |
| 293 tileSize.fWidth = buffer.readInt(); | 358 tileSize.fWidth = buffer.readInt(); |
| 294 tileSize.fHeight = buffer.readInt(); | 359 tileSize.fHeight = buffer.readInt(); |
| 295 | 360 |
| 296 switch (type) { | 361 switch (type) { |
| 297 case kFractalNoise_Type: | 362 case kFractalNoise_Type: |
| 298 return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves
, seed, &tileSize); | 363 return SkPerlinNoiseShader2::CreateFractalNoise(freqX, freqY, octave
s, seed, &tileSize); |
| 299 case kTurbulence_Type: | 364 case kTurbulence_Type: |
| 300 return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, s
eed, &tileSize); | 365 return SkPerlinNoiseShader2::CreateTubulence(freqX, freqY, octaves,
seed, &tileSize); |
| 366 case kImprovedNoise_Type: |
| 367 return SkPerlinNoiseShader2::CreateImprovedNoise(freqX, freqY, octav
es, seed); |
| 301 default: | 368 default: |
| 302 return nullptr; | 369 return nullptr; |
| 303 } | 370 } |
| 304 } | 371 } |
| 305 | 372 |
| 306 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const { | 373 void SkPerlinNoiseShader2::flatten(SkWriteBuffer& buffer) const { |
| 307 buffer.writeInt((int) fType); | 374 buffer.writeInt((int) fType); |
| 308 buffer.writeScalar(fBaseFrequencyX); | 375 buffer.writeScalar(fBaseFrequencyX); |
| 309 buffer.writeScalar(fBaseFrequencyY); | 376 buffer.writeScalar(fBaseFrequencyY); |
| 310 buffer.writeInt(fNumOctaves); | 377 buffer.writeInt(fNumOctaves); |
| 311 buffer.writeScalar(fSeed); | 378 buffer.writeScalar(fSeed); |
| 312 buffer.writeInt(fTileSize.fWidth); | 379 buffer.writeInt(fTileSize.fWidth); |
| 313 buffer.writeInt(fTileSize.fHeight); | 380 buffer.writeInt(fTileSize.fHeight); |
| 314 } | 381 } |
| 315 | 382 |
| 316 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( | 383 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::noise2D( |
| 317 int channel, const StitchData& stitchData, const SkPoint& noiseVector) c
onst { | 384 int channel, const StitchData& stitchData, const SkPoint& noiseVector) c
onst { |
| 318 struct Noise { | 385 struct Noise { |
| 319 int noisePositionIntegerValue; | 386 int noisePositionIntegerValue; |
| 320 int nextNoisePositionIntegerValue; | 387 int nextNoisePositionIntegerValue; |
| 321 SkScalar noisePositionFractionValue; | 388 SkScalar noisePositionFractionValue; |
| 322 Noise(SkScalar component) | 389 Noise(SkScalar component) |
| 323 { | 390 { |
| 324 SkScalar position = component + kPerlinNoise; | 391 SkScalar position = component + kPerlinNoise; |
| 325 noisePositionIntegerValue = SkScalarFloorToInt(position); | 392 noisePositionIntegerValue = SkScalarFloorToInt(position); |
| 326 noisePositionFractionValue = position - SkIntToScalar(noisePositionI
ntegerValue); | 393 noisePositionFractionValue = position - SkIntToScalar(noisePositionI
ntegerValue); |
| 327 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; | 394 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; |
| 328 } | 395 } |
| 329 }; | 396 }; |
| 330 Noise noiseX(noiseVector.x()); | 397 Noise noiseX(noiseVector.x()); |
| 331 Noise noiseY(noiseVector.y()); | 398 Noise noiseY(noiseVector.y()); |
| 332 SkScalar u, v; | 399 SkScalar u, v; |
| 333 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi
seShader&>(fShader); | 400 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNo
iseShader2&>(fShader); |
| 334 // If stitching, adjust lattice points accordingly. | 401 // If stitching, adjust lattice points accordingly. |
| 335 if (perlinNoiseShader.fStitchTiles) { | 402 if (perlinNoiseShader.fStitchTiles) { |
| 336 noiseX.noisePositionIntegerValue = | 403 noiseX.noisePositionIntegerValue = |
| 337 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit
chData.fWidth); | 404 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stit
chData.fWidth); |
| 338 noiseY.noisePositionIntegerValue = | 405 noiseY.noisePositionIntegerValue = |
| 339 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit
chData.fHeight); | 406 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stit
chData.fHeight); |
| 340 noiseX.nextNoisePositionIntegerValue = | 407 noiseX.nextNoisePositionIntegerValue = |
| 341 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX,
stitchData.fWidth); | 408 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX,
stitchData.fWidth); |
| 342 noiseY.nextNoisePositionIntegerValue = | 409 noiseY.nextNoisePositionIntegerValue = |
| 343 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY,
stitchData.fHeight); | 410 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY,
stitchData.fHeight); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 364 v = fPaintingData->fGradient[channel][b10].dot(fractionValue); | 431 v = fPaintingData->fGradient[channel][b10].dot(fractionValue); |
| 365 SkScalar a = SkScalarInterp(u, v, sx); | 432 SkScalar a = SkScalarInterp(u, v, sx); |
| 366 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) | 433 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) |
| 367 v = fPaintingData->fGradient[channel][b11].dot(fractionValue); | 434 v = fPaintingData->fGradient[channel][b11].dot(fractionValue); |
| 368 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) | 435 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) |
| 369 u = fPaintingData->fGradient[channel][b01].dot(fractionValue); | 436 u = fPaintingData->fGradient[channel][b01].dot(fractionValue); |
| 370 SkScalar b = SkScalarInterp(u, v, sx); | 437 SkScalar b = SkScalarInterp(u, v, sx); |
| 371 return SkScalarInterp(a, b, sy); | 438 return SkScalarInterp(a, b, sy); |
| 372 } | 439 } |
| 373 | 440 |
| 374 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValue
ForPoint( | 441 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateTurbulenceValu
eForPoint( |
| 375 int channel, StitchData& stitchData, const SkPoint& point) const { | 442 int channel, StitchData& stitchData, const SkPoint& point) const { |
| 376 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoi
seShader&>(fShader); | 443 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNo
iseShader2&>(fShader); |
| 377 if (perlinNoiseShader.fStitchTiles) { | 444 if (perlinNoiseShader.fStitchTiles) { |
| 378 // Set up TurbulenceInitial stitch values. | 445 // Set up TurbulenceInitial stitch values. |
| 379 stitchData = fPaintingData->fStitchDataInit; | 446 stitchData = fPaintingData->fStitchDataInit; |
| 380 } | 447 } |
| 381 SkScalar turbulenceFunctionResult = 0; | 448 SkScalar turbulenceFunctionResult = 0; |
| 382 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBas
eFrequency.fX), | 449 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBas
eFrequency.fX), |
| 383 SkScalarMul(point.y(), fPaintingData->fBas
eFrequency.fY))); | 450 SkScalarMul(point.y(), fPaintingData->fBas
eFrequency.fY))); |
| 384 SkScalar ratio = SK_Scalar1; | 451 SkScalar ratio = SK_Scalar1; |
| 385 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { | 452 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { |
| 386 SkScalar noise = noise2D(channel, stitchData, noiseVector); | 453 SkScalar noise = noise2D(channel, stitchData, noiseVector); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 407 } | 474 } |
| 408 | 475 |
| 409 if (channel == 3) { // Scale alpha by paint value | 476 if (channel == 3) { // Scale alpha by paint value |
| 410 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; | 477 turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; |
| 411 } | 478 } |
| 412 | 479 |
| 413 // Clamp result | 480 // Clamp result |
| 414 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); | 481 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); |
| 415 } | 482 } |
| 416 | 483 |
| 417 SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade( | 484 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 485 // Improved Perlin Noise based on Java implementation found at http://mrl.nyu.ed
u/~perlin/noise/ |
| 486 static SkScalar fade(SkScalar t) { |
| 487 return t * t * t * (t * (t * 6 - 15) + 10); |
| 488 } |
| 489 |
| 490 static SkScalar lerp(SkScalar t, SkScalar a, SkScalar b) { |
| 491 return a + t * (b - a); |
| 492 } |
| 493 |
| 494 static SkScalar grad(int hash, SkScalar x, SkScalar y, SkScalar z) { |
| 495 int h = hash & 15; |
| 496 SkScalar u = h < 8 ? x : y; |
| 497 SkScalar v = h < 4 ? y : h == 12 || h == 14 ? x : z; |
| 498 return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); |
| 499 } |
| 500 |
| 501 SkScalar SkPerlinNoiseShader2::PerlinNoiseShaderContext::calculateImprovedNoiseV
alueForPoint( |
| 502 int channel, const SkPoint& point) const { |
| 503 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNo
iseShader2&>(fShader); |
| 504 SkScalar x = point.fX * perlinNoiseShader.fBaseFrequencyX; |
| 505 SkScalar y = point.fY * perlinNoiseShader.fBaseFrequencyY; |
| 506 // z offset between different channels, chosen arbitrarily |
| 507 static const SkScalar CHANNEL_DELTA = 1000.0f; |
| 508 SkScalar z = channel * CHANNEL_DELTA + perlinNoiseShader.fSeed; |
| 509 SkScalar result = 0; |
| 510 SkScalar ratio = SK_Scalar1; |
| 511 for (int i = 0; i < perlinNoiseShader.fNumOctaves; i++) { |
| 512 int X = SkScalarFloorToInt(x) & 255; |
| 513 int Y = SkScalarFloorToInt(y) & 255; |
| 514 int Z = SkScalarFloorToInt(z) & 255; |
| 515 SkScalar px = x - SkScalarFloorToScalar(x); |
| 516 SkScalar py = y - SkScalarFloorToScalar(y); |
| 517 SkScalar pz = z - SkScalarFloorToScalar(z); |
| 518 SkScalar u = fade(px); |
| 519 SkScalar v = fade(py); |
| 520 SkScalar w = fade(pz); |
| 521 uint8_t* permutations = improved_noise_permutations; |
| 522 int A = permutations[X] + Y; |
| 523 int AA = permutations[A] + Z; |
| 524 int AB = permutations[A + 1] + Z; |
| 525 int B = permutations[X + 1] + Y; |
| 526 int BA = permutations[B] + Z; |
| 527 int BB = permutations[B + 1] + Z; |
| 528 result += lerp(w, lerp(v, lerp(u, grad(permutations[AA ], px , py
, pz ), |
| 529 grad(permutations[BA ], px - 1, py
, pz )), |
| 530 lerp(u, grad(permutations[AB ], px , py
- 1, pz ), |
| 531 grad(permutations[BB ], px - 1, py
- 1, pz ))), |
| 532 lerp(v, lerp(u, grad(permutations[AA + 1], px , py
, pz - 1), |
| 533 grad(permutations[BA + 1], px - 1, py
, pz - 1)), |
| 534 lerp(u, grad(permutations[AB + 1], px , py
- 1, pz - 1), |
| 535 grad(permutations[BB + 1], px - 1, py
- 1, pz - 1)))) / |
| 536 ratio; |
| 537 x *= 2; |
| 538 y *= 2; |
| 539 ratio *= 2; |
| 540 } |
| 541 result = SkScalarClampMax((result + 1.0f) / 2.0f, 1.0f); |
| 542 return result; |
| 543 } |
| 544 ////////////////////////////////////////////////////////////////////////////////
//////////////////// |
| 545 |
| 546 SkPMColor SkPerlinNoiseShader2::PerlinNoiseShaderContext::shade( |
| 418 const SkPoint& point, StitchData& stitchData) const { | 547 const SkPoint& point, StitchData& stitchData) const { |
| 548 const SkPerlinNoiseShader2& perlinNoiseShader = static_cast<const SkPerlinNo
iseShader2&>(fShader); |
| 419 SkPoint newPoint; | 549 SkPoint newPoint; |
| 420 fMatrix.mapPoints(&newPoint, &point, 1); | 550 fMatrix.mapPoints(&newPoint, &point, 1); |
| 421 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); | 551 newPoint.fX = SkScalarRoundToScalar(newPoint.fX); |
| 422 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); | 552 newPoint.fY = SkScalarRoundToScalar(newPoint.fY); |
| 423 | 553 |
| 424 U8CPU rgba[4]; | 554 U8CPU rgba[4]; |
| 425 for (int channel = 3; channel >= 0; --channel) { | 555 for (int channel = 3; channel >= 0; --channel) { |
| 426 rgba[channel] = SkScalarFloorToInt(255 * | 556 SkScalar value; |
| 427 calculateTurbulenceValueForPoint(channel, stitchData, newPoint)); | 557 if (perlinNoiseShader.fType == kImprovedNoise_Type) { |
| 558 value = calculateImprovedNoiseValueForPoint(channel, newPoint); |
| 559 } |
| 560 else { |
| 561 value = calculateTurbulenceValueForPoint(channel, stitchData, newPoi
nt); |
| 562 } |
| 563 rgba[channel] = SkScalarFloorToInt(255 * value); |
| 428 } | 564 } |
| 429 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); | 565 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]); |
| 430 } | 566 } |
| 431 | 567 |
| 432 SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec, | 568 SkShader::Context* SkPerlinNoiseShader2::onCreateContext(const ContextRec& rec, |
| 433 void* storage) const { | 569 void* storage) const { |
| 434 return new (storage) PerlinNoiseShaderContext(*this, rec); | 570 return new (storage) PerlinNoiseShaderContext(*this, rec); |
| 435 } | 571 } |
| 436 | 572 |
| 437 size_t SkPerlinNoiseShader::contextSize() const { | 573 size_t SkPerlinNoiseShader2::contextSize() const { |
| 438 return sizeof(PerlinNoiseShaderContext); | 574 return sizeof(PerlinNoiseShaderContext); |
| 439 } | 575 } |
| 440 | 576 |
| 441 SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext( | 577 SkPerlinNoiseShader2::PerlinNoiseShaderContext::PerlinNoiseShaderContext( |
| 442 const SkPerlinNoiseShader& shader, const ContextRec& rec) | 578 const SkPerlinNoiseShader2& shader, const ContextRec& rec) |
| 443 : INHERITED(shader, rec) | 579 : INHERITED(shader, rec) |
| 444 { | 580 { |
| 445 SkMatrix newMatrix = *rec.fMatrix; | 581 SkMatrix newMatrix = *rec.fMatrix; |
| 446 newMatrix.preConcat(shader.getLocalMatrix()); | 582 newMatrix.preConcat(shader.getLocalMatrix()); |
| 447 if (rec.fLocalMatrix) { | 583 if (rec.fLocalMatrix) { |
| 448 newMatrix.preConcat(*rec.fLocalMatrix); | 584 newMatrix.preConcat(*rec.fLocalMatrix); |
| 449 } | 585 } |
| 450 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi
se | 586 // This (1,1) translation is due to WebKit's 1 based coordinates for the noi
se |
| 451 // (as opposed to 0 based, usually). The same adjustment is in the setData()
function. | 587 // (as opposed to 0 based, usually). The same adjustment is in the setData()
function. |
| 452 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.get
TranslateY() + SK_Scalar1); | 588 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.get
TranslateY() + SK_Scalar1); |
| 453 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBas
eFrequencyX, | 589 fPaintingData = new PaintingData(shader.fTileSize, shader.fSeed, shader.fBas
eFrequencyX, |
| 454 shader.fBaseFrequencyY, newMatrix); | 590 shader.fBaseFrequencyY, newMatrix); |
| 455 } | 591 } |
| 456 | 592 |
| 457 SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { del
ete fPaintingData; } | 593 SkPerlinNoiseShader2::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() { de
lete fPaintingData; } |
| 458 | 594 |
| 459 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan( | 595 void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan( |
| 460 int x, int y, SkPMColor result[], int count) { | 596 int x, int y, SkPMColor result[], int count) { |
| 461 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); | 597 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); |
| 462 StitchData stitchData; | 598 StitchData stitchData; |
| 463 for (int i = 0; i < count; ++i) { | 599 for (int i = 0; i < count; ++i) { |
| 464 result[i] = shade(point, stitchData); | 600 result[i] = shade(point, stitchData); |
| 465 point.fX += SK_Scalar1; | 601 point.fX += SK_Scalar1; |
| 466 } | 602 } |
| 467 } | 603 } |
| 468 | 604 |
| 469 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16( | 605 void SkPerlinNoiseShader2::PerlinNoiseShaderContext::shadeSpan16( |
| 470 int x, int y, uint16_t result[], int count) { | 606 int x, int y, uint16_t result[], int count) { |
| 471 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); | 607 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y)); |
| 472 StitchData stitchData; | 608 StitchData stitchData; |
| 473 DITHER_565_SCAN(y); | 609 DITHER_565_SCAN(y); |
| 474 for (int i = 0; i < count; ++i) { | 610 for (int i = 0; i < count; ++i) { |
| 475 unsigned dither = DITHER_VALUE(x); | 611 unsigned dither = DITHER_VALUE(x); |
| 476 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); | 612 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither); |
| 477 DITHER_INC_X(x); | 613 DITHER_INC_X(x); |
| 478 point.fX += SK_Scalar1; | 614 point.fX += SK_Scalar1; |
| 479 } | 615 } |
| 480 } | 616 } |
| 481 | 617 |
| 482 ///////////////////////////////////////////////////////////////////// | 618 ///////////////////////////////////////////////////////////////////// |
| 483 | 619 |
| 484 #if SK_SUPPORT_GPU | 620 #if SK_SUPPORT_GPU |
| 485 | 621 |
| 486 class GrGLPerlinNoise : public GrGLFragmentProcessor { | 622 class GrGLPerlinNoise2 : public GrGLFragmentProcessor { |
| 487 public: | 623 public: |
| 488 GrGLPerlinNoise(const GrProcessor&); | 624 GrGLPerlinNoise2(const GrProcessor&); |
| 489 virtual ~GrGLPerlinNoise() {} | 625 virtual ~GrGLPerlinNoise2() {} |
| 490 | 626 |
| 491 virtual void emitCode(EmitArgs&) override; | 627 virtual void emitCode(EmitArgs&) override; |
| 492 | 628 |
| 493 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor
KeyBuilder* b); | 629 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor
KeyBuilder* b); |
| 494 | 630 |
| 495 protected: | 631 protected: |
| 496 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; | 632 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; |
| 497 | 633 |
| 498 private: | 634 private: |
| 499 | 635 |
| 500 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; | 636 GrGLSLProgramDataManager::UniformHandle fStitchDataUni; |
| 501 SkPerlinNoiseShader::Type fType; | 637 SkPerlinNoiseShader2::Type fType; |
| 502 bool fStitchTiles; | 638 bool fStitchTiles; |
| 503 int fNumOctaves; | 639 int fNumOctaves; |
| 504 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; | 640 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; |
| 505 | 641 |
| 506 private: | 642 private: |
| 507 typedef GrGLFragmentProcessor INHERITED; | 643 typedef GrGLFragmentProcessor INHERITED; |
| 508 }; | 644 }; |
| 509 | 645 |
| 510 ///////////////////////////////////////////////////////////////////// | 646 ///////////////////////////////////////////////////////////////////// |
| 511 | 647 |
| 512 class GrPerlinNoiseEffect : public GrFragmentProcessor { | 648 class GrPerlinNoise2Effect : public GrFragmentProcessor { |
| 513 public: | 649 public: |
| 514 static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type, | 650 static GrFragmentProcessor* Create(SkPerlinNoiseShader2::Type type, |
| 515 int numOctaves, bool stitchTiles, | 651 int numOctaves, bool stitchTiles, |
| 516 SkPerlinNoiseShader::PaintingData* painti
ngData, | 652 SkPerlinNoiseShader2::PaintingData* paint
ingData, |
| 517 GrTexture* permutationsTexture, GrTexture
* noiseTexture, | 653 GrTexture* permutationsTexture, GrTexture
* noiseTexture, |
| 518 const SkMatrix& matrix) { | 654 const SkMatrix& matrix) { |
| 519 return new GrPerlinNoiseEffect(type, numOctaves, stitchTiles, paintingDa
ta, | 655 return new GrPerlinNoise2Effect(type, numOctaves, stitchTiles, paintingD
ata, |
| 520 permutationsTexture, noiseTexture, matrix
); | 656 permutationsTexture, noiseTexture, matrix
); |
| 521 } | 657 } |
| 522 | 658 |
| 523 virtual ~GrPerlinNoiseEffect() { delete fPaintingData; } | 659 virtual ~GrPerlinNoise2Effect() { delete fPaintingData; } |
| 524 | 660 |
| 525 const char* name() const override { return "PerlinNoise"; } | 661 const char* name() const override { return "PerlinNoise"; } |
| 526 | 662 |
| 527 const SkPerlinNoiseShader::StitchData& stitchData() const { return fPainting
Data->fStitchDataInit; } | 663 const SkPerlinNoiseShader2::StitchData& stitchData() const { return fPaintin
gData->fStitchDataInit; } |
| 528 | 664 |
| 529 SkPerlinNoiseShader::Type type() const { return fType; } | 665 SkPerlinNoiseShader2::Type type() const { return fType; } |
| 530 bool stitchTiles() const { return fStitchTiles; } | 666 bool stitchTiles() const { return fStitchTiles; } |
| 531 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency
; } | 667 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency
; } |
| 532 int numOctaves() const { return fNumOctaves; } | 668 int numOctaves() const { return fNumOctaves; } |
| 533 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } | 669 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } |
| 534 | 670 |
| 535 private: | 671 private: |
| 536 GrGLFragmentProcessor* onCreateGLInstance() const override { | 672 GrGLFragmentProcessor* onCreateGLInstance() const override { |
| 537 return new GrGLPerlinNoise(*this); | 673 return new GrGLPerlinNoise2(*this); |
| 538 } | 674 } |
| 539 | 675 |
| 540 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, | 676 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, |
| 541 GrProcessorKeyBuilder* b) const override { | 677 GrProcessorKeyBuilder* b) const override { |
| 542 GrGLPerlinNoise::GenKey(*this, caps, b); | 678 GrGLPerlinNoise2::GenKey(*this, caps, b); |
| 543 } | 679 } |
| 544 | 680 |
| 545 bool onIsEqual(const GrFragmentProcessor& sBase) const override { | 681 bool onIsEqual(const GrFragmentProcessor& sBase) const override { |
| 546 const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>(); | 682 const GrPerlinNoise2Effect& s = sBase.cast<GrPerlinNoise2Effect>(); |
| 547 return fType == s.fType && | 683 return fType == s.fType && |
| 548 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency
&& | 684 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency
&& |
| 549 fNumOctaves == s.fNumOctaves && | 685 fNumOctaves == s.fNumOctaves && |
| 550 fStitchTiles == s.fStitchTiles && | 686 fStitchTiles == s.fStitchTiles && |
| 551 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataIni
t; | 687 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataIni
t; |
| 552 } | 688 } |
| 553 | 689 |
| 554 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { | 690 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 555 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); | 691 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); |
| 556 } | 692 } |
| 557 | 693 |
| 558 GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type, | 694 GrPerlinNoise2Effect(SkPerlinNoiseShader2::Type type, |
| 559 int numOctaves, bool stitchTiles, | 695 int numOctaves, bool stitchTiles, |
| 560 SkPerlinNoiseShader::PaintingData* paintingData, | 696 SkPerlinNoiseShader2::PaintingData* paintingData, |
| 561 GrTexture* permutationsTexture, GrTexture* noiseTexture, | 697 GrTexture* permutationsTexture, GrTexture* noiseTexture, |
| 562 const SkMatrix& matrix) | 698 const SkMatrix& matrix) |
| 563 : fType(type) | 699 : fType(type) |
| 564 , fNumOctaves(numOctaves) | 700 , fNumOctaves(numOctaves) |
| 565 , fStitchTiles(stitchTiles) | 701 , fStitchTiles(stitchTiles) |
| 566 , fPermutationsAccess(permutationsTexture) | 702 , fPermutationsAccess(permutationsTexture) |
| 567 , fNoiseAccess(noiseTexture) | 703 , fNoiseAccess(noiseTexture) |
| 568 , fPaintingData(paintingData) { | 704 , fPaintingData(paintingData) { |
| 569 this->initClassID<GrPerlinNoiseEffect>(); | 705 this->initClassID<GrPerlinNoise2Effect>(); |
| 570 this->addTextureAccess(&fPermutationsAccess); | 706 this->addTextureAccess(&fPermutationsAccess); |
| 571 this->addTextureAccess(&fNoiseAccess); | 707 this->addTextureAccess(&fNoiseAccess); |
| 572 fCoordTransform.reset(kLocal_GrCoordSet, matrix); | 708 fCoordTransform.reset(kLocal_GrCoordSet, matrix); |
| 573 this->addCoordTransform(&fCoordTransform); | 709 this->addCoordTransform(&fCoordTransform); |
| 574 } | 710 } |
| 575 | 711 |
| 576 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; | 712 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
| 577 | 713 |
| 578 SkPerlinNoiseShader::Type fType; | 714 SkPerlinNoiseShader2::Type fType; |
| 579 GrCoordTransform fCoordTransform; | 715 GrCoordTransform fCoordTransform; |
| 580 int fNumOctaves; | 716 int fNumOctaves; |
| 581 bool fStitchTiles; | 717 bool fStitchTiles; |
| 582 GrTextureAccess fPermutationsAccess; | 718 GrTextureAccess fPermutationsAccess; |
| 583 GrTextureAccess fNoiseAccess; | 719 GrTextureAccess fNoiseAccess; |
| 584 SkPerlinNoiseShader::PaintingData *fPaintingData; | 720 SkPerlinNoiseShader2::PaintingData *fPaintingData; |
| 585 | 721 |
| 586 private: | 722 private: |
| 587 typedef GrFragmentProcessor INHERITED; | 723 typedef GrFragmentProcessor INHERITED; |
| 588 }; | 724 }; |
| 589 | 725 |
| 590 ///////////////////////////////////////////////////////////////////// | 726 ///////////////////////////////////////////////////////////////////// |
| 591 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect); | 727 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoise2Effect); |
| 592 | 728 |
| 593 const GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(GrProcessorTestData*
d) { | 729 const GrFragmentProcessor* GrPerlinNoise2Effect::TestCreate(GrProcessorTestData*
d) { |
| 594 int numOctaves = d->fRandom->nextRangeU(2, 10); | 730 int numOctaves = d->fRandom->nextRangeU(2, 10); |
| 595 bool stitchTiles = d->fRandom->nextBool(); | 731 bool stitchTiles = d->fRandom->nextBool(); |
| 596 SkScalar seed = SkIntToScalar(d->fRandom->nextU()); | 732 SkScalar seed = SkIntToScalar(d->fRandom->nextU()); |
| 597 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096), | 733 SkISize tileSize = SkISize::Make(d->fRandom->nextRangeU(4, 4096), |
| 598 d->fRandom->nextRangeU(4, 4096)); | 734 d->fRandom->nextRangeU(4, 4096)); |
| 599 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, | 735 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, |
| 600 0.99f); | 736 0.99f); |
| 601 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, | 737 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, |
| 602 0.99f); | 738 0.99f); |
| 603 | 739 |
| 604 SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ? | 740 SkAutoTUnref<SkShader> shader(d->fRandom->nextBool() ? |
| 605 SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY,
numOctaves, seed, | 741 SkPerlinNoiseShader2::CreateFractalNoise(baseFrequencyX, baseFrequencyY,
numOctaves, seed, |
| 606 stitchTiles ? &tileSize : nullpt
r) : | 742 stitchTiles ? &tileSize : nullpt
r) : |
| 607 SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, nu
mOctaves, seed, | 743 SkPerlinNoiseShader2::CreateTurbulence(baseFrequencyX, baseFrequencyY, n
umOctaves, seed, |
| 608 stitchTiles ? &tileSize : nullptr))
; | 744 stitchTiles ? &tileSize : nullptr))
; |
| 609 | 745 |
| 610 GrPaint grPaint; | 746 GrPaint grPaint; |
| 611 return shader->asFragmentProcessor(d->fContext, | 747 return shader->asFragmentProcessor(d->fContext, |
| 612 GrTest::TestMatrix(d->fRandom), nullptr, | 748 GrTest::TestMatrix(d->fRandom), nullptr, |
| 613 kNone_SkFilterQuality); | 749 kNone_SkFilterQuality); |
| 614 } | 750 } |
| 615 | 751 |
| 616 GrGLPerlinNoise::GrGLPerlinNoise(const GrProcessor& processor) | 752 GrGLPerlinNoise2::GrGLPerlinNoise2(const GrProcessor& processor) |
| 617 : fType(processor.cast<GrPerlinNoiseEffect>().type()) | 753 : fType(processor.cast<GrPerlinNoise2Effect>().type()) |
| 618 , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles()) | 754 , fStitchTiles(processor.cast<GrPerlinNoise2Effect>().stitchTiles()) |
| 619 , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) { | 755 , fNumOctaves(processor.cast<GrPerlinNoise2Effect>().numOctaves()) { |
| 620 } | 756 } |
| 621 | 757 |
| 622 void GrGLPerlinNoise::emitCode(EmitArgs& args) { | 758 void GrGLPerlinNoise2::emitCode(EmitArgs& args) { |
| 623 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); | 759 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
| 624 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0); | 760 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0); |
| 625 | 761 |
| 626 fBaseFrequencyUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_
Visibility, | 762 fBaseFrequencyUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_
Visibility, |
| 627 kVec2f_GrSLType, kDefault_GrSLPrecis
ion, | 763 kVec2f_GrSLType, kDefault_GrSLPrecis
ion, |
| 628 "baseFrequency"); | 764 "baseFrequency"); |
| 629 const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyU
ni); | 765 const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyU
ni); |
| 630 | 766 |
| 631 const char* stitchDataUni = nullptr; | 767 const char* stitchDataUni = nullptr; |
| 632 if (fStitchTiles) { | 768 if (fStitchTiles) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 // Set up TurbulenceInitial stitch values. | 948 // Set up TurbulenceInitial stitch values. |
| 813 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni)
; | 949 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni)
; |
| 814 } | 950 } |
| 815 | 951 |
| 816 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); | 952 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); |
| 817 | 953 |
| 818 // Loop over all octaves | 954 // Loop over all octaves |
| 819 fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {"
, fNumOctaves); | 955 fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {"
, fNumOctaves); |
| 820 | 956 |
| 821 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor); | 957 fsBuilder->codeAppendf("\n\t\t\t%s += ", args.fOutputColor); |
| 822 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { | 958 if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) { |
| 823 fsBuilder->codeAppend("abs("); | 959 fsBuilder->codeAppend("abs("); |
| 824 } | 960 } |
| 825 if (fStitchTiles) { | 961 if (fStitchTiles) { |
| 826 fsBuilder->codeAppendf( | 962 fsBuilder->codeAppendf( |
| 827 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," | 963 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s)," |
| 828 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", | 964 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))", |
| 829 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, | 965 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, |
| 830 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, | 966 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, |
| 831 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, | 967 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, |
| 832 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); | 968 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); |
| 833 } else { | 969 } else { |
| 834 fsBuilder->codeAppendf( | 970 fsBuilder->codeAppendf( |
| 835 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," | 971 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s)," |
| 836 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", | 972 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))", |
| 837 noiseFuncName.c_str(), chanCoordR, noiseVec, | 973 noiseFuncName.c_str(), chanCoordR, noiseVec, |
| 838 noiseFuncName.c_str(), chanCoordG, noiseVec, | 974 noiseFuncName.c_str(), chanCoordG, noiseVec, |
| 839 noiseFuncName.c_str(), chanCoordB, noiseVec, | 975 noiseFuncName.c_str(), chanCoordB, noiseVec, |
| 840 noiseFuncName.c_str(), chanCoordA, noiseVec); | 976 noiseFuncName.c_str(), chanCoordA, noiseVec); |
| 841 } | 977 } |
| 842 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { | 978 if (fType != SkPerlinNoiseShader2::kFractalNoise_Type) { |
| 843 fsBuilder->codeAppendf(")"); // end of "abs(" | 979 fsBuilder->codeAppendf(")"); // end of "abs(" |
| 844 } | 980 } |
| 845 fsBuilder->codeAppendf(" * %s;", ratio); | 981 fsBuilder->codeAppendf(" * %s;", ratio); |
| 846 | 982 |
| 847 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); | 983 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); |
| 848 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); | 984 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); |
| 849 | 985 |
| 850 if (fStitchTiles) { | 986 if (fStitchTiles) { |
| 851 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); | 987 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); |
| 852 } | 988 } |
| 853 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves | 989 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves |
| 854 | 990 |
| 855 if (fType == SkPerlinNoiseShader::kFractalNoise_Type) { | 991 if (fType == SkPerlinNoiseShader2::kFractalNoise_Type) { |
| 856 // The value of turbulenceFunctionResult comes from ((turbulenceFunction
Result) + 1) / 2 | 992 // The value of turbulenceFunctionResult comes from ((turbulenceFunction
Result) + 1) / 2 |
| 857 // by fractalNoise and (turbulenceFunctionResult) by turbulence. | 993 // by fractalNoise and (turbulenceFunctionResult) by turbulence. |
| 858 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", | 994 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", |
| 859 args.fOutputColor,args.fOutputColor); | 995 args.fOutputColor,args.fOutputColor); |
| 860 } | 996 } |
| 861 | 997 |
| 862 // Clamp values | 998 // Clamp values |
| 863 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor,
args.fOutputColor); | 999 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", args.fOutputColor,
args.fOutputColor); |
| 864 | 1000 |
| 865 // Pre-multiply the result | 1001 // Pre-multiply the result |
| 866 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", | 1002 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", |
| 867 args.fOutputColor, args.fOutputColor, | 1003 args.fOutputColor, args.fOutputColor, |
| 868 args.fOutputColor, args.fOutputColor); | 1004 args.fOutputColor, args.fOutputColor); |
| 869 } | 1005 } |
| 870 | 1006 |
| 871 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLCaps&, | 1007 void GrGLPerlinNoise2::GenKey(const GrProcessor& processor, const GrGLSLCaps&, |
| 872 GrProcessorKeyBuilder* b) { | 1008 GrProcessorKeyBuilder* b) { |
| 873 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(
); | 1009 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect
>(); |
| 874 | 1010 |
| 875 uint32_t key = turbulence.numOctaves(); | 1011 uint32_t key = turbulence.numOctaves(); |
| 876 | 1012 |
| 877 key = key << 3; // Make room for next 3 bits | 1013 key = key << 3; // Make room for next 3 bits |
| 878 | 1014 |
| 879 switch (turbulence.type()) { | 1015 switch (turbulence.type()) { |
| 880 case SkPerlinNoiseShader::kFractalNoise_Type: | 1016 case SkPerlinNoiseShader2::kFractalNoise_Type: |
| 881 key |= 0x1; | 1017 key |= 0x1; |
| 882 break; | 1018 break; |
| 883 case SkPerlinNoiseShader::kTurbulence_Type: | 1019 case SkPerlinNoiseShader2::kTurbulence_Type: |
| 884 key |= 0x2; | 1020 key |= 0x2; |
| 885 break; | 1021 break; |
| 886 default: | 1022 default: |
| 887 // leave key at 0 | 1023 // leave key at 0 |
| 888 break; | 1024 break; |
| 889 } | 1025 } |
| 890 | 1026 |
| 891 if (turbulence.stitchTiles()) { | 1027 if (turbulence.stitchTiles()) { |
| 892 key |= 0x4; // Flip the 3rd bit if tile stitching is on | 1028 key |= 0x4; // Flip the 3rd bit if tile stitching is on |
| 893 } | 1029 } |
| 894 | 1030 |
| 895 b->add32(key); | 1031 b->add32(key); |
| 896 } | 1032 } |
| 897 | 1033 |
| 898 void GrGLPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman, | 1034 void GrGLPerlinNoise2::onSetData(const GrGLSLProgramDataManager& pdman, |
| 899 const GrProcessor& processor) { | 1035 const GrProcessor& processor) { |
| 900 INHERITED::onSetData(pdman, processor); | 1036 INHERITED::onSetData(pdman, processor); |
| 901 | 1037 |
| 902 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>(
); | 1038 const GrPerlinNoise2Effect& turbulence = processor.cast<GrPerlinNoise2Effect
>(); |
| 903 | 1039 |
| 904 const SkVector& baseFrequency = turbulence.baseFrequency(); | 1040 const SkVector& baseFrequency = turbulence.baseFrequency(); |
| 905 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); | 1041 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); |
| 906 | 1042 |
| 907 if (turbulence.stitchTiles()) { | 1043 if (turbulence.stitchTiles()) { |
| 908 const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchDat
a(); | 1044 const SkPerlinNoiseShader2::StitchData& stitchData = turbulence.stitchDa
ta(); |
| 909 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), | 1045 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth), |
| 910 SkIntToScalar(stitchData.fHeight)); | 1046 SkIntToScalar(stitchData.fHeight)); |
| 911 } | 1047 } |
| 912 } | 1048 } |
| 913 | 1049 |
| 914 ///////////////////////////////////////////////////////////////////// | 1050 ///////////////////////////////////////////////////////////////////// |
| 915 const GrFragmentProcessor* SkPerlinNoiseShader::asFragmentProcessor( | 1051 |
| 1052 class GrGLImprovedPerlinNoise : public GrGLFragmentProcessor { |
| 1053 public: |
| 1054 GrGLImprovedPerlinNoise(const GrProcessor&); |
| 1055 virtual ~GrGLImprovedPerlinNoise() {} |
| 1056 |
| 1057 virtual void emitCode(EmitArgs&) override; |
| 1058 |
| 1059 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessor
KeyBuilder* b); |
| 1060 |
| 1061 protected: |
| 1062 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override
; |
| 1063 |
| 1064 private: |
| 1065 |
| 1066 SkScalar fZ; |
| 1067 GrGLSLProgramDataManager::UniformHandle fZUni; |
| 1068 GrGLSLProgramDataManager::UniformHandle fOctavesUni; |
| 1069 GrGLSLProgramDataManager::UniformHandle fBaseFrequencyUni; |
| 1070 |
| 1071 private: |
| 1072 typedef GrGLFragmentProcessor INHERITED; |
| 1073 }; |
| 1074 |
| 1075 ///////////////////////////////////////////////////////////////////// |
| 1076 |
| 1077 class GrImprovedPerlinNoiseEffect : public GrFragmentProcessor { |
| 1078 public: |
| 1079 static GrFragmentProcessor* Create(SkScalar octaves, SkScalar z, |
| 1080 SkPerlinNoiseShader2::PaintingData* paint
ingData, |
| 1081 GrTexture* permutationsTexture, GrTexture
* gradientTexture, |
| 1082 const SkMatrix& matrix) { |
| 1083 return new GrImprovedPerlinNoiseEffect(octaves, z, paintingData, permuta
tionsTexture, |
| 1084 gradientTexture, matrix); |
| 1085 } |
| 1086 |
| 1087 virtual ~GrImprovedPerlinNoiseEffect() { delete fPaintingData; } |
| 1088 |
| 1089 const char* name() const override { return "ImprovedPerlinNoise"; } |
| 1090 |
| 1091 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency
; } |
| 1092 SkScalar z() const { return fZ; } |
| 1093 int octaves() const { return fOctaves; } |
| 1094 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); } |
| 1095 |
| 1096 private: |
| 1097 GrGLFragmentProcessor* onCreateGLInstance() const override { |
| 1098 return new GrGLImprovedPerlinNoise(*this); |
| 1099 } |
| 1100 |
| 1101 virtual void onGetGLProcessorKey(const GrGLSLCaps& caps, |
| 1102 GrProcessorKeyBuilder* b) const override { |
| 1103 GrGLImprovedPerlinNoise::GenKey(*this, caps, b); |
| 1104 } |
| 1105 |
| 1106 bool onIsEqual(const GrFragmentProcessor& sBase) const override { |
| 1107 const GrImprovedPerlinNoiseEffect& s = sBase.cast<GrImprovedPerlinNoiseE
ffect>(); |
| 1108 return fZ == fZ && |
| 1109 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency; |
| 1110 } |
| 1111 |
| 1112 void onComputeInvariantOutput(GrInvariantOutput* inout) const override { |
| 1113 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); |
| 1114 } |
| 1115 |
| 1116 GrImprovedPerlinNoiseEffect(int octaves, SkScalar z, |
| 1117 SkPerlinNoiseShader2::PaintingData* paintingData
, |
| 1118 GrTexture* permutationsTexture, GrTexture* gradi
entTexture, |
| 1119 const SkMatrix& matrix) |
| 1120 : fOctaves(octaves) |
| 1121 , fZ(z) |
| 1122 , fPermutationsAccess(permutationsTexture) |
| 1123 , fGradientAccess(gradientTexture) |
| 1124 , fPaintingData(paintingData) { |
| 1125 this->initClassID<GrImprovedPerlinNoiseEffect>(); |
| 1126 this->addTextureAccess(&fPermutationsAccess); |
| 1127 this->addTextureAccess(&fGradientAccess); |
| 1128 fCoordTransform.reset(kLocal_GrCoordSet, matrix); |
| 1129 this->addCoordTransform(&fCoordTransform); |
| 1130 } |
| 1131 |
| 1132 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; |
| 1133 |
| 1134 GrCoordTransform fCoordTransform; |
| 1135 int fOctaves; |
| 1136 SkScalar fZ; |
| 1137 GrTextureAccess fPermutationsAccess; |
| 1138 GrTextureAccess fGradientAccess; |
| 1139 SkPerlinNoiseShader2::PaintingData *fPaintingData; |
| 1140 |
| 1141 private: |
| 1142 typedef GrFragmentProcessor INHERITED; |
| 1143 }; |
| 1144 |
| 1145 ///////////////////////////////////////////////////////////////////// |
| 1146 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrImprovedPerlinNoiseEffect); |
| 1147 |
| 1148 const GrFragmentProcessor* GrImprovedPerlinNoiseEffect::TestCreate(GrProcessorTe
stData* d) { |
| 1149 SkScalar baseFrequencyX = d->fRandom->nextRangeScalar(0.01f, |
| 1150 0.99f); |
| 1151 SkScalar baseFrequencyY = d->fRandom->nextRangeScalar(0.01f, |
| 1152 0.99f); |
| 1153 int numOctaves = d->fRandom->nextRangeU(2, 10); |
| 1154 SkScalar z = SkIntToScalar(d->fRandom->nextU()); |
| 1155 |
| 1156 SkAutoTUnref<SkShader> shader(SkPerlinNoiseShader2::CreateImprovedNoise(base
FrequencyX, |
| 1157 baseF
requencyY, |
| 1158 numOc
taves, |
| 1159 z)); |
| 1160 |
| 1161 GrPaint grPaint; |
| 1162 return shader->asFragmentProcessor(d->fContext, |
| 1163 GrTest::TestMatrix(d->fRandom), nullptr, |
| 1164 kNone_SkFilterQuality); |
| 1165 } |
| 1166 |
| 1167 GrGLImprovedPerlinNoise::GrGLImprovedPerlinNoise(const GrProcessor& processor) |
| 1168 : fZ(processor.cast<GrImprovedPerlinNoiseEffect>().z()) { |
| 1169 } |
| 1170 |
| 1171 void GrGLImprovedPerlinNoise::emitCode(EmitArgs& args) { |
| 1172 GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); |
| 1173 SkString vCoords = fsBuilder->ensureFSCoords2D(args.fCoords, 0); |
| 1174 |
| 1175 fBaseFrequencyUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_
Visibility, |
| 1176 kVec2f_GrSLType, kDefault_GrSLPrecis
ion, |
| 1177 "baseFrequency"); |
| 1178 const char* baseFrequencyUni = args.fBuilder->getUniformCStr(fBaseFrequencyU
ni); |
| 1179 |
| 1180 fOctavesUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibi
lity, |
| 1181 kFloat_GrSLType, kDefault_GrSLPrecision, |
| 1182 "octaves"); |
| 1183 const char* octavesUni = args.fBuilder->getUniformCStr(fOctavesUni); |
| 1184 |
| 1185 fZUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, |
| 1186 kFloat_GrSLType, kDefault_GrSLPrecision, |
| 1187 "z"); |
| 1188 const char* zUni = args.fBuilder->getUniformCStr(fZUni); |
| 1189 |
| 1190 // fade function |
| 1191 static const GrGLSLShaderVar fadeArgs[] = { |
| 1192 GrGLSLShaderVar("t", kVec3f_GrSLType) |
| 1193 }; |
| 1194 SkString fadeFuncName; |
| 1195 fsBuilder->emitFunction(kVec3f_GrSLType, "fade", SK_ARRAY_COUNT(fadeArgs), |
| 1196 fadeArgs, |
| 1197 "return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);",
|
| 1198 &fadeFuncName); |
| 1199 |
| 1200 // perm function |
| 1201 static const GrGLSLShaderVar permArgs[] = { |
| 1202 GrGLSLShaderVar("x", kFloat_GrSLType) |
| 1203 }; |
| 1204 SkString permFuncName; |
| 1205 SkString permCode("return "); |
| 1206 // FIXME even though I'm creating these textures with kRepeat_TileMode, they
're clamped. Not |
| 1207 // sure why. Using fract() (here and the next texture lookup) as a workaroun
d. |
| 1208 fsBuilder->appendTextureLookup(&permCode, args.fSamplers[0], "vec2(fract(x /
256.0), 0.0)", |
| 1209 kVec2f_GrSLType); |
| 1210 permCode.append(".r * 255.0;"); |
| 1211 fsBuilder->emitFunction(kFloat_GrSLType, "perm", SK_ARRAY_COUNT(permArgs), p
ermArgs, |
| 1212 permCode.c_str(), &permFuncName); |
| 1213 |
| 1214 // grad function |
| 1215 static const GrGLSLShaderVar gradArgs[] = { |
| 1216 GrGLSLShaderVar("x", kFloat_GrSLType), |
| 1217 GrGLSLShaderVar("p", kVec3f_GrSLType) |
| 1218 }; |
| 1219 SkString gradFuncName; |
| 1220 SkString gradCode("return dot("); |
| 1221 fsBuilder->appendTextureLookup(&gradCode, args.fSamplers[1], "vec2(fract(x /
16.0), 0.0)", |
| 1222 kVec2f_GrSLType); |
| 1223 gradCode.append(".rgb * 255.0 - vec3(1.0), p);"); |
| 1224 fsBuilder->emitFunction(kFloat_GrSLType, "grad", SK_ARRAY_COUNT(gradArgs), g
radArgs, |
| 1225 gradCode.c_str(), &gradFuncName); |
| 1226 |
| 1227 // lerp function |
| 1228 static const GrGLSLShaderVar lerpArgs[] = { |
| 1229 GrGLSLShaderVar("a", kFloat_GrSLType), |
| 1230 GrGLSLShaderVar("b", kFloat_GrSLType), |
| 1231 GrGLSLShaderVar("w", kFloat_GrSLType) |
| 1232 }; |
| 1233 SkString lerpFuncName; |
| 1234 fsBuilder->emitFunction(kFloat_GrSLType, "lerp", SK_ARRAY_COUNT(lerpArgs), l
erpArgs, |
| 1235 "return a + w * (b - a);", &lerpFuncName); |
| 1236 |
| 1237 // noise function |
| 1238 static const GrGLSLShaderVar noiseArgs[] = { |
| 1239 GrGLSLShaderVar("p", kVec3f_GrSLType), |
| 1240 }; |
| 1241 SkString noiseFuncName; |
| 1242 SkString noiseCode; |
| 1243 noiseCode.append("vec3 P = mod(floor(p), 256.0);"); |
| 1244 noiseCode.append("p -= floor(p);"); |
| 1245 noiseCode.appendf("vec3 f = %s(p);", fadeFuncName.c_str()); |
| 1246 noiseCode.appendf("float A = %s(P.x) + P.y;", permFuncName.c_str()); |
| 1247 noiseCode.appendf("float AA = %s(A) + P.z;", permFuncName.c_str()); |
| 1248 noiseCode.appendf("float AB = %s(A + 1.0) + P.z;", permFuncName.c_str()); |
| 1249 noiseCode.appendf("float B = %s(P.x + 1.0) + P.y;", permFuncName.c_str()); |
| 1250 noiseCode.appendf("float BA = %s(B) + P.z;", permFuncName.c_str()); |
| 1251 noiseCode.appendf("float BB = %s(B + 1.0) + P.z;", permFuncName.c_str()); |
| 1252 noiseCode.appendf("float result = %s(", lerpFuncName.c_str()); |
| 1253 noiseCode.appendf("%s(%s(%s(%s(AA), p),", lerpFuncName.c_str(), lerpFuncName
.c_str(), |
| 1254 gradFuncName.c_str(), permFuncName.c_str()); |
| 1255 noiseCode.appendf("%s(%s(BA), p + vec3(-1.0, 0.0, 0.0)), f.x),", gradFuncNam
e.c_str(), |
| 1256 permFuncName.c_str()); |
| 1257 noiseCode.appendf("%s(%s(%s(AB), p + vec3(0.0, -1.0, 0.0)),", lerpFuncName.c
_str(), |
| 1258 gradFuncName.c_str(), permFuncName.c_str()); |
| 1259 noiseCode.appendf("%s(%s(BB), p + vec3(-1.0, -1.0, 0.0)), f.x), f.y),", |
| 1260 gradFuncName.c_str(), permFuncName.c_str()); |
| 1261 noiseCode.appendf("%s(%s(%s(%s(AA + 1.0), p + vec3(0.0, 0.0, -1.0)),", |
| 1262 lerpFuncName.c_str(), lerpFuncName.c_str(), gradFuncName.c
_str(), |
| 1263 permFuncName.c_str()); |
| 1264 noiseCode.appendf("%s(%s(BA + 1.0), p + vec3(-1.0, 0.0, -1.0)), f.x),", |
| 1265 gradFuncName.c_str(), permFuncName.c_str()); |
| 1266 noiseCode.appendf("%s(%s(%s(AB + 1.0), p + vec3(0.0, -1.0, -1.0)),", |
| 1267 lerpFuncName.c_str(), gradFuncName.c_str(), permFuncName.c
_str()); |
| 1268 noiseCode.appendf("%s(%s(BB + 1.0), p + vec3(-1.0, -1.0, -1.0)), f.x), f.y),
f.z);", |
| 1269 gradFuncName.c_str(), permFuncName.c_str()); |
| 1270 noiseCode.append("return result;"); |
| 1271 fsBuilder->emitFunction(kFloat_GrSLType, "noise", SK_ARRAY_COUNT(noiseArgs),
noiseArgs, |
| 1272 noiseCode.c_str(), &noiseFuncName); |
| 1273 |
| 1274 // noiseOctaves function |
| 1275 static const GrGLSLShaderVar noiseOctavesArgs[] = { |
| 1276 GrGLSLShaderVar("p", kVec3f_GrSLType), |
| 1277 GrGLSLShaderVar("octaves", kFloat_GrSLType), |
| 1278 }; |
| 1279 SkString noiseOctavesFuncName; |
| 1280 SkString noiseOctavesCode; |
| 1281 noiseOctavesCode.append("float result = 0.0;"); |
| 1282 noiseOctavesCode.append("float ratio = 1.0;"); |
| 1283 noiseOctavesCode.append("for (float i = 0.0; i < octaves; i++) {"); |
| 1284 noiseOctavesCode.appendf("result += %s(p) / ratio;", noiseFuncName.c_str()); |
| 1285 noiseOctavesCode.append("p *= 2.0;"); |
| 1286 noiseOctavesCode.append("ratio *= 2.0;"); |
| 1287 noiseOctavesCode.append("}"); |
| 1288 noiseOctavesCode.append("return (result + 1.0) / 2.0;"); |
| 1289 fsBuilder->emitFunction(kFloat_GrSLType, "noiseOctaves", SK_ARRAY_COUNT(nois
eOctavesArgs), |
| 1290 noiseOctavesArgs, noiseOctavesCode.c_str(), &noiseOc
tavesFuncName); |
| 1291 |
| 1292 fsBuilder->codeAppendf("vec2 coords = %s * %s;", vCoords.c_str(), baseFreque
ncyUni); |
| 1293 fsBuilder->codeAppendf("float r = %s(vec3(coords, %s), %s);", noiseOctavesFu
ncName.c_str(), |
| 1294 zUni, octavesUni); |
| 1295 fsBuilder->codeAppendf("float g = %s(vec3(coords, %s + 1000.0), %s);", |
| 1296 noiseOctavesFuncName.c_str(), zUni, octavesUni); |
| 1297 fsBuilder->codeAppendf("float b = %s(vec3(coords, %s + 2000.0), %s);", |
| 1298 noiseOctavesFuncName.c_str(), zUni, octavesUni); |
| 1299 fsBuilder->codeAppendf("float a = %s(vec3(coords, %s + 3000.0), %s);", |
| 1300 noiseOctavesFuncName.c_str(), zUni, octavesUni); |
| 1301 fsBuilder->codeAppendf("%s = vec4(r, g, b, a);", args.fOutputColor); |
| 1302 |
| 1303 // Clamp values |
| 1304 fsBuilder->codeAppendf("%s = clamp(%s, 0.0, 1.0);", args.fOutputColor, args.
fOutputColor); |
| 1305 |
| 1306 // Pre-multiply the result |
| 1307 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", |
| 1308 args.fOutputColor, args.fOutputColor, |
| 1309 args.fOutputColor, args.fOutputColor); |
| 1310 } |
| 1311 |
| 1312 void GrGLImprovedPerlinNoise::GenKey(const GrProcessor& processor, const GrGLSLC
aps&, |
| 1313 GrProcessorKeyBuilder* b) { |
| 1314 } |
| 1315 |
| 1316 void GrGLImprovedPerlinNoise::onSetData(const GrGLSLProgramDataManager& pdman, |
| 1317 const GrProcessor& processor) { |
| 1318 INHERITED::onSetData(pdman, processor); |
| 1319 |
| 1320 const GrImprovedPerlinNoiseEffect& noise = processor.cast<GrImprovedPerlinNo
iseEffect>(); |
| 1321 |
| 1322 const SkVector& baseFrequency = noise.baseFrequency(); |
| 1323 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY); |
| 1324 |
| 1325 pdman.set1f(fOctavesUni, noise.octaves()); |
| 1326 |
| 1327 pdman.set1f(fZUni, noise.z()); |
| 1328 } |
| 1329 |
| 1330 ///////////////////////////////////////////////////////////////////// |
| 1331 const GrFragmentProcessor* SkPerlinNoiseShader2::asFragmentProcessor( |
| 916 GrContext* context, | 1332 GrContext* context, |
| 917 const SkMatrix& viewM, | 1333 const SkMatrix& viewM, |
| 918 const SkMatrix* externalLoca
lMatrix, | 1334 const SkMatrix* externalLoca
lMatrix, |
| 919 SkFilterQuality) const { | 1335 SkFilterQuality) const { |
| 920 SkASSERT(context); | 1336 SkASSERT(context); |
| 921 | 1337 |
| 922 SkMatrix localMatrix = this->getLocalMatrix(); | 1338 SkMatrix localMatrix = this->getLocalMatrix(); |
| 923 if (externalLocalMatrix) { | 1339 if (externalLocalMatrix) { |
| 924 localMatrix.preConcat(*externalLocalMatrix); | 1340 localMatrix.preConcat(*externalLocalMatrix); |
| 925 } | 1341 } |
| 926 | 1342 |
| 927 SkMatrix matrix = viewM; | 1343 SkMatrix matrix = viewM; |
| 928 matrix.preConcat(localMatrix); | 1344 matrix.preConcat(localMatrix); |
| 929 | 1345 |
| 1346 // Either we don't stitch tiles, either we have a valid tile size |
| 1347 SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); |
| 1348 |
| 1349 SkPerlinNoiseShader2::PaintingData* paintingData = |
| 1350 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY,
matrix); |
| 1351 |
| 1352 SkMatrix m = viewM; |
| 1353 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); |
| 1354 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); |
| 1355 |
| 1356 if (fType == kImprovedNoise_Type) { |
| 1357 GrTextureParams textureParams(SkShader::TileMode::kRepeat_TileMode, |
| 1358 GrTextureParams::FilterMode::kNone_FilterM
ode); |
| 1359 SkAutoTUnref<GrTexture> permutationsTexture( |
| 1360 GrRefCachedBitmapTexture(context, paintingData->getImprovedPermutati
onsBitmap(), |
| 1361 textureParams)); |
| 1362 SkAutoTUnref<GrTexture> gradientTexture( |
| 1363 GrRefCachedBitmapTexture(context, paintingData->getGradientBitmap(), |
| 1364 textureParams)); |
| 1365 return GrImprovedPerlinNoiseEffect::Create(fNumOctaves, fSeed, paintingD
ata, |
| 1366 permutationsTexture, gradient
Texture, m); |
| 1367 } |
| 1368 |
| 930 if (0 == fNumOctaves) { | 1369 if (0 == fNumOctaves) { |
| 931 if (kFractalNoise_Type == fType) { | 1370 if (kFractalNoise_Type == fType) { |
| 932 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) | 1371 // Extract the incoming alpha and emit rgba = (a/4, a/4, a/4, a/2) |
| 933 SkAutoTUnref<const GrFragmentProcessor> inner( | 1372 SkAutoTUnref<const GrFragmentProcessor> inner( |
| 934 GrConstColorProcessor::Create(0x80404040, | 1373 GrConstColorProcessor::Create(0x80404040, |
| 935 GrConstColorProcessor::kModulateRG
BA_InputMode)); | 1374 GrConstColorProcessor::kModulateRG
BA_InputMode)); |
| 936 return GrFragmentProcessor::MulOutputByInputAlpha(inner); | 1375 return GrFragmentProcessor::MulOutputByInputAlpha(inner); |
| 937 } | 1376 } |
| 938 // Emit zero. | 1377 // Emit zero. |
| 939 return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore
_InputMode); | 1378 return GrConstColorProcessor::Create(0x0, GrConstColorProcessor::kIgnore
_InputMode); |
| 940 } | 1379 } |
| 941 | 1380 |
| 942 // Either we don't stitch tiles, either we have a valid tile size | |
| 943 SkASSERT(!fStitchTiles || !fTileSize.isEmpty()); | |
| 944 | |
| 945 SkPerlinNoiseShader::PaintingData* paintingData = | |
| 946 new PaintingData(fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY,
matrix); | |
| 947 SkAutoTUnref<GrTexture> permutationsTexture( | 1381 SkAutoTUnref<GrTexture> permutationsTexture( |
| 948 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), | 1382 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), |
| 949 GrTextureParams::ClampNoFilter())); | 1383 GrTextureParams::ClampNoFilter())); |
| 950 SkAutoTUnref<GrTexture> noiseTexture( | 1384 SkAutoTUnref<GrTexture> noiseTexture( |
| 951 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), | 1385 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), |
| 952 GrTextureParams::ClampNoFilter())); | 1386 GrTextureParams::ClampNoFilter())); |
| 953 | 1387 |
| 954 SkMatrix m = viewM; | |
| 955 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1); | |
| 956 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1); | |
| 957 if ((permutationsTexture) && (noiseTexture)) { | 1388 if ((permutationsTexture) && (noiseTexture)) { |
| 958 SkAutoTUnref<GrFragmentProcessor> inner( | 1389 SkAutoTUnref<GrFragmentProcessor> inner( |
| 959 GrPerlinNoiseEffect::Create(fType, | 1390 GrPerlinNoise2Effect::Create(fType, |
| 960 fNumOctaves, | 1391 fNumOctaves, |
| 961 fStitchTiles, | 1392 fStitchTiles, |
| 962 paintingData, | 1393 paintingData, |
| 963 permutationsTexture, noiseTexture, | 1394 permutationsTexture, noiseTexture, |
| 964 m)); | 1395 m)); |
| 965 return GrFragmentProcessor::MulOutputByInputAlpha(inner); | 1396 return GrFragmentProcessor::MulOutputByInputAlpha(inner); |
| 966 } | 1397 } |
| 967 delete paintingData; | 1398 delete paintingData; |
| 968 return nullptr; | 1399 return nullptr; |
| 969 } | 1400 } |
| 970 | 1401 |
| 971 #endif | 1402 #endif |
| 972 | 1403 |
| 973 #ifndef SK_IGNORE_TO_STRING | 1404 #ifndef SK_IGNORE_TO_STRING |
| 974 void SkPerlinNoiseShader::toString(SkString* str) const { | 1405 void SkPerlinNoiseShader2::toString(SkString* str) const { |
| 975 str->append("SkPerlinNoiseShader: ("); | 1406 str->append("SkPerlinNoiseShader2: ("); |
| 976 | 1407 |
| 977 str->append("type: "); | 1408 str->append("type: "); |
| 978 switch (fType) { | 1409 switch (fType) { |
| 979 case kFractalNoise_Type: | 1410 case kFractalNoise_Type: |
| 980 str->append("\"fractal noise\""); | 1411 str->append("\"fractal noise\""); |
| 981 break; | 1412 break; |
| 982 case kTurbulence_Type: | 1413 case kTurbulence_Type: |
| 983 str->append("\"turbulence\""); | 1414 str->append("\"turbulence\""); |
| 984 break; | 1415 break; |
| 985 default: | 1416 default: |
| 986 str->append("\"unknown\""); | 1417 str->append("\"unknown\""); |
| 987 break; | 1418 break; |
| 988 } | 1419 } |
| 989 str->append(" base frequency: ("); | 1420 str->append(" base frequency: ("); |
| 990 str->appendScalar(fBaseFrequencyX); | 1421 str->appendScalar(fBaseFrequencyX); |
| 991 str->append(", "); | 1422 str->append(", "); |
| 992 str->appendScalar(fBaseFrequencyY); | 1423 str->appendScalar(fBaseFrequencyY); |
| 993 str->append(") number of octaves: "); | 1424 str->append(") number of octaves: "); |
| 994 str->appendS32(fNumOctaves); | 1425 str->appendS32(fNumOctaves); |
| 995 str->append(" seed: "); | 1426 str->append(" seed: "); |
| 996 str->appendScalar(fSeed); | 1427 str->appendScalar(fSeed); |
| 997 str->append(" stitch tiles: "); | 1428 str->append(" stitch tiles: "); |
| 998 str->append(fStitchTiles ? "true " : "false "); | 1429 str->append(fStitchTiles ? "true " : "false "); |
| 999 | 1430 |
| 1000 this->INHERITED::toString(str); | 1431 this->INHERITED::toString(str); |
| 1001 | 1432 |
| 1002 str->append(")"); | 1433 str->append(")"); |
| 1003 } | 1434 } |
| 1004 #endif | 1435 #endif |
| OLD | NEW |