2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
9 #include "SkPerlinNoiseShader.h"
10 #include "SkColorFilter.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
14 #include "SkUnPreMultiply.h"
18 #include "GrContext.h"
19 #include "GrCoordTransform.h"
20 #include "gl/GrGLProcessor.h"
21 #include "gl/builders/GrGLProgramBuilder.h"
22 #include "GrTBackendProcessorFactory.h"
26 static const int kBlockSize = 256;
27 static const int kBlockMask = kBlockSize - 1;
28 static const int kPerlinNoise = 4096;
29 static const int kRandMaximum = SK_MaxS32; // 2**31 - 1
33 // noiseValue is the color component's value (or color)
34 // limitValue is the maximum perlin noise array index value allowed
35 // newValue is the current noise dimension (either width or height)
36 inline int checkNoise(int noiseValue, int limitValue, int newValue) {
37 // If the noise value would bring us out of bounds of the current noise array while we are
38 // stiching noise tiles together, wrap the noise around the current dimension of the noise to
39 // stay within the array bounds in a continuous fashion (so that tiling lines are not visible)
40 if (noiseValue >= limitValue) {
41 noiseValue -= newValue;
46 inline SkScalar smoothCurve(SkScalar t) {
47 static const SkScalar SK_Scalar3 = 3.0f;
49 // returns t * t * (3 - 2 * t)
50 return SkScalarMul(SkScalarSquare(t), SK_Scalar3 - 2 * t);
53 bool perlin_noise_type_is_valid(SkPerlinNoiseShader::Type type) {
54 return (SkPerlinNoiseShader::kFractalNoise_Type == type) ||
55 (SkPerlinNoiseShader::kTurbulence_Type == type);
60 struct SkPerlinNoiseShader::StitchData {
68 bool operator==(const StitchData& other) const {
69 return fWidth == other.fWidth &&
70 fWrapX == other.fWrapX &&
71 fHeight == other.fHeight &&
72 fWrapY == other.fWrapY;
75 int fWidth; // How much to subtract to wrap for stitching.
76 int fWrapX; // Minimum value to wrap.
81 struct SkPerlinNoiseShader::PaintingData {
82 PaintingData(const SkISize& tileSize, SkScalar seed,
83 SkScalar baseFrequencyX, SkScalar baseFrequencyY,
84 const SkMatrix& matrix)
86 SkVector wavelength = SkVector::Make(SkScalarInvert(baseFrequencyX),
87 SkScalarInvert(baseFrequencyY));
88 matrix.mapVectors(&wavelength, 1);
89 fBaseFrequency.fX = SkScalarInvert(wavelength.fX);
90 fBaseFrequency.fY = SkScalarInvert(wavelength.fY);
91 SkVector sizeVec = SkVector::Make(SkIntToScalar(tileSize.fWidth),
92 SkIntToScalar(tileSize.fHeight));
93 matrix.mapVectors(&sizeVec, 1);
94 fTileSize.fWidth = SkScalarRoundToInt(sizeVec.fX);
95 fTileSize.fHeight = SkScalarRoundToInt(sizeVec.fY);
97 if (!fTileSize.isEmpty()) {
102 fPermutationsBitmap.setInfo(SkImageInfo::MakeA8(kBlockSize, 1));
103 fPermutationsBitmap.setPixels(fLatticeSelector);
105 fNoiseBitmap.setInfo(SkImageInfo::MakeN32Premul(kBlockSize, 4));
106 fNoiseBitmap.setPixels(fNoise[0][0]);
111 uint8_t fLatticeSelector[kBlockSize];
112 uint16_t fNoise[4][kBlockSize][2];
113 SkPoint fGradient[4][kBlockSize];
115 SkVector fBaseFrequency;
116 StitchData fStitchDataInit;
121 SkBitmap fPermutationsBitmap;
122 SkBitmap fNoiseBitmap;
125 inline int random() {
126 static const int gRandAmplitude = 16807; // 7**5; primitive root of m
127 static const int gRandQ = 127773; // m / a
128 static const int gRandR = 2836; // m % a
130 int result = gRandAmplitude * (fSeed % gRandQ) - gRandR * (fSeed / gRandQ);
132 result += kRandMaximum;
137 // Only called once. Could be part of the constructor.
138 void init(SkScalar seed)
140 static const SkScalar gInvBlockSizef = SkScalarInvert(SkIntToScalar(kBlockSize));
142 // According to the SVG spec, we must truncate (not round) the seed value.
143 fSeed = SkScalarTruncToInt(seed);
144 // The seed value clamp to the range [1, kRandMaximum - 1].
146 fSeed = -(fSeed % (kRandMaximum - 1)) + 1;
148 if (fSeed > kRandMaximum - 1) {
149 fSeed = kRandMaximum - 1;
151 for (int channel = 0; channel < 4; ++channel) {
152 for (int i = 0; i < kBlockSize; ++i) {
153 fLatticeSelector[i] = i;
154 fNoise[channel][i][0] = (random() % (2 * kBlockSize));
155 fNoise[channel][i][1] = (random() % (2 * kBlockSize));
158 for (int i = kBlockSize - 1; i > 0; --i) {
159 int k = fLatticeSelector[i];
160 int j = random() % kBlockSize;
162 SkASSERT(j < kBlockSize);
163 fLatticeSelector[i] = fLatticeSelector[j];
164 fLatticeSelector[j] = k;
167 // Perform the permutations now
170 uint16_t noise[4][kBlockSize][2];
171 for (int i = 0; i < kBlockSize; ++i) {
172 for (int channel = 0; channel < 4; ++channel) {
173 for (int j = 0; j < 2; ++j) {
174 noise[channel][i][j] = fNoise[channel][i][j];
178 // Do permutations on noise data
179 for (int i = 0; i < kBlockSize; ++i) {
180 for (int channel = 0; channel < 4; ++channel) {
181 for (int j = 0; j < 2; ++j) {
182 fNoise[channel][i][j] = noise[channel][fLatticeSelector[i]][j];
188 // Half of the largest possible value for 16 bit unsigned int
189 static const SkScalar gHalfMax16bits = 32767.5f;
191 // Compute gradients from permutated noise data
192 for (int channel = 0; channel < 4; ++channel) {
193 for (int i = 0; i < kBlockSize; ++i) {
194 fGradient[channel][i] = SkPoint::Make(
195 SkScalarMul(SkIntToScalar(fNoise[channel][i][0] - kBlockSize),
197 SkScalarMul(SkIntToScalar(fNoise[channel][i][1] - kBlockSize),
199 fGradient[channel][i].normalize();
200 // Put the normalized gradient back into the noise data
201 fNoise[channel][i][0] = SkScalarRoundToInt(SkScalarMul(
202 fGradient[channel][i].fX + SK_Scalar1, gHalfMax16bits));
203 fNoise[channel][i][1] = SkScalarRoundToInt(SkScalarMul(
204 fGradient[channel][i].fY + SK_Scalar1, gHalfMax16bits));
209 // Only called once. Could be part of the constructor.
211 SkScalar tileWidth = SkIntToScalar(fTileSize.width());
212 SkScalar tileHeight = SkIntToScalar(fTileSize.height());
213 SkASSERT(tileWidth > 0 && tileHeight > 0);
214 // When stitching tiled turbulence, the frequencies must be adjusted
215 // so that the tile borders will be continuous.
216 if (fBaseFrequency.fX) {
217 SkScalar lowFrequencx =
218 SkScalarFloorToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
219 SkScalar highFrequencx =
220 SkScalarCeilToScalar(tileWidth * fBaseFrequency.fX) / tileWidth;
221 // BaseFrequency should be non-negative according to the standard.
222 if (SkScalarDiv(fBaseFrequency.fX, lowFrequencx) <
223 SkScalarDiv(highFrequencx, fBaseFrequency.fX)) {
224 fBaseFrequency.fX = lowFrequencx;
226 fBaseFrequency.fX = highFrequencx;
229 if (fBaseFrequency.fY) {
230 SkScalar lowFrequency =
231 SkScalarFloorToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
232 SkScalar highFrequency =
233 SkScalarCeilToScalar(tileHeight * fBaseFrequency.fY) / tileHeight;
234 if (SkScalarDiv(fBaseFrequency.fY, lowFrequency) <
235 SkScalarDiv(highFrequency, fBaseFrequency.fY)) {
236 fBaseFrequency.fY = lowFrequency;
238 fBaseFrequency.fY = highFrequency;
241 // Set up TurbulenceInitial stitch values.
242 fStitchDataInit.fWidth =
243 SkScalarRoundToInt(tileWidth * fBaseFrequency.fX);
244 fStitchDataInit.fWrapX = kPerlinNoise + fStitchDataInit.fWidth;
245 fStitchDataInit.fHeight =
246 SkScalarRoundToInt(tileHeight * fBaseFrequency.fY);
247 fStitchDataInit.fWrapY = kPerlinNoise + fStitchDataInit.fHeight;
253 const SkBitmap& getPermutationsBitmap() const { return fPermutationsBitmap; }
255 const SkBitmap& getNoiseBitmap() const { return fNoiseBitmap; }
259 SkShader* SkPerlinNoiseShader::CreateFractalNoise(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
260 int numOctaves, SkScalar seed,
261 const SkISize* tileSize) {
262 return SkNEW_ARGS(SkPerlinNoiseShader, (kFractalNoise_Type, baseFrequencyX, baseFrequencyY,
263 numOctaves, seed, tileSize));
266 SkShader* SkPerlinNoiseShader::CreateTurbulence(SkScalar baseFrequencyX, SkScalar baseFrequencyY,
267 int numOctaves, SkScalar seed,
268 const SkISize* tileSize) {
269 return SkNEW_ARGS(SkPerlinNoiseShader, (kTurbulence_Type, baseFrequencyX, baseFrequencyY,
270 numOctaves, seed, tileSize));
273 SkPerlinNoiseShader::SkPerlinNoiseShader(SkPerlinNoiseShader::Type type,
274 SkScalar baseFrequencyX,
275 SkScalar baseFrequencyY,
278 const SkISize* tileSize)
280 , fBaseFrequencyX(baseFrequencyX)
281 , fBaseFrequencyY(baseFrequencyY)
282 , fNumOctaves(numOctaves > 255 ? 255 : numOctaves/*[0,255] octaves allowed*/)
284 , fTileSize(NULL == tileSize ? SkISize::Make(0, 0) : *tileSize)
285 , fStitchTiles(!fTileSize.isEmpty())
287 SkASSERT(numOctaves >= 0 && numOctaves < 256);
290 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
291 SkPerlinNoiseShader::SkPerlinNoiseShader(SkReadBuffer& buffer) : INHERITED(buffer) {
292 fType = (SkPerlinNoiseShader::Type) buffer.readInt();
293 fBaseFrequencyX = buffer.readScalar();
294 fBaseFrequencyY = buffer.readScalar();
295 fNumOctaves = buffer.readInt();
296 fSeed = buffer.readScalar();
297 fStitchTiles = buffer.readBool();
298 fTileSize.fWidth = buffer.readInt();
299 fTileSize.fHeight = buffer.readInt();
300 buffer.validate(perlin_noise_type_is_valid(fType) &&
301 (fNumOctaves >= 0) && (fNumOctaves <= 255) &&
302 (fStitchTiles != fTileSize.isEmpty()));
306 SkPerlinNoiseShader::~SkPerlinNoiseShader() {
309 SkFlattenable* SkPerlinNoiseShader::CreateProc(SkReadBuffer& buffer) {
310 Type type = (Type)buffer.readInt();
311 SkScalar freqX = buffer.readScalar();
312 SkScalar freqY = buffer.readScalar();
313 int octaves = buffer.readInt();
314 SkScalar seed = buffer.readScalar();
316 tileSize.fWidth = buffer.readInt();
317 tileSize.fHeight = buffer.readInt();
320 case kFractalNoise_Type:
321 return SkPerlinNoiseShader::CreateFractalNoise(freqX, freqY, octaves, seed, &tileSize);
322 case kTurbulence_Type:
323 return SkPerlinNoiseShader::CreateTubulence(freqX, freqY, octaves, seed, &tileSize);
329 void SkPerlinNoiseShader::flatten(SkWriteBuffer& buffer) const {
330 buffer.writeInt((int) fType);
331 buffer.writeScalar(fBaseFrequencyX);
332 buffer.writeScalar(fBaseFrequencyY);
333 buffer.writeInt(fNumOctaves);
334 buffer.writeScalar(fSeed);
335 buffer.writeInt(fTileSize.fWidth);
336 buffer.writeInt(fTileSize.fHeight);
339 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
340 int channel, const StitchData& stitchData, const SkPoint& noiseVector) const {
342 int noisePositionIntegerValue;
343 int nextNoisePositionIntegerValue;
344 SkScalar noisePositionFractionValue;
345 Noise(SkScalar component)
347 SkScalar position = component + kPerlinNoise;
348 noisePositionIntegerValue = SkScalarFloorToInt(position);
349 noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue);
350 nextNoisePositionIntegerValue = noisePositionIntegerValue + 1;
353 Noise noiseX(noiseVector.x());
354 Noise noiseY(noiseVector.y());
356 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
357 // If stitching, adjust lattice points accordingly.
358 if (perlinNoiseShader.fStitchTiles) {
359 noiseX.noisePositionIntegerValue =
360 checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
361 noiseY.noisePositionIntegerValue =
362 checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
363 noiseX.nextNoisePositionIntegerValue =
364 checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth);
365 noiseY.nextNoisePositionIntegerValue =
366 checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight);
368 noiseX.noisePositionIntegerValue &= kBlockMask;
369 noiseY.noisePositionIntegerValue &= kBlockMask;
370 noiseX.nextNoisePositionIntegerValue &= kBlockMask;
371 noiseY.nextNoisePositionIntegerValue &= kBlockMask;
373 fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue];
375 fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue];
376 int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask;
377 int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask;
378 int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
379 int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask;
380 SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue);
381 SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue);
382 // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement
383 SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue,
384 noiseY.noisePositionFractionValue); // Offset (0,0)
385 u = fPaintingData->fGradient[channel][b00].dot(fractionValue);
386 fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
387 v = fPaintingData->fGradient[channel][b10].dot(fractionValue);
388 SkScalar a = SkScalarInterp(u, v, sx);
389 fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
390 v = fPaintingData->fGradient[channel][b11].dot(fractionValue);
391 fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
392 u = fPaintingData->fGradient[channel][b01].dot(fractionValue);
393 SkScalar b = SkScalarInterp(u, v, sx);
394 return SkScalarInterp(a, b, sy);
397 SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint(
398 int channel, StitchData& stitchData, const SkPoint& point) const {
399 const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader);
400 if (perlinNoiseShader.fStitchTiles) {
401 // Set up TurbulenceInitial stitch values.
402 stitchData = fPaintingData->fStitchDataInit;
404 SkScalar turbulenceFunctionResult = 0;
405 SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX),
406 SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY)));
407 SkScalar ratio = SK_Scalar1;
408 for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) {
409 SkScalar noise = noise2D(channel, stitchData, noiseVector);
410 turbulenceFunctionResult += SkScalarDiv(
411 (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise), ratio);
415 if (perlinNoiseShader.fStitchTiles) {
416 // Update stitch values
417 stitchData.fWidth *= 2;
418 stitchData.fWrapX = stitchData.fWidth + kPerlinNoise;
419 stitchData.fHeight *= 2;
420 stitchData.fWrapY = stitchData.fHeight + kPerlinNoise;
424 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
425 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
426 if (perlinNoiseShader.fType == kFractalNoise_Type) {
427 turbulenceFunctionResult =
428 SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf;
431 if (channel == 3) { // Scale alpha by paint value
432 turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult,
433 SkScalarDiv(SkIntToScalar(getPaintAlpha()), SkIntToScalar(255)));
437 return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1);
440 SkPMColor SkPerlinNoiseShader::PerlinNoiseShaderContext::shade(
441 const SkPoint& point, StitchData& stitchData) const {
443 fMatrix.mapPoints(&newPoint, &point, 1);
444 newPoint.fX = SkScalarRoundToScalar(newPoint.fX);
445 newPoint.fY = SkScalarRoundToScalar(newPoint.fY);
448 for (int channel = 3; channel >= 0; --channel) {
449 rgba[channel] = SkScalarFloorToInt(255 *
450 calculateTurbulenceValueForPoint(channel, stitchData, newPoint));
452 return SkPreMultiplyARGB(rgba[3], rgba[0], rgba[1], rgba[2]);
455 SkShader::Context* SkPerlinNoiseShader::onCreateContext(const ContextRec& rec,
456 void* storage) const {
457 return SkNEW_PLACEMENT_ARGS(storage, PerlinNoiseShaderContext, (*this, rec));
460 size_t SkPerlinNoiseShader::contextSize() const {
461 return sizeof(PerlinNoiseShaderContext);
464 SkPerlinNoiseShader::PerlinNoiseShaderContext::PerlinNoiseShaderContext(
465 const SkPerlinNoiseShader& shader, const ContextRec& rec)
466 : INHERITED(shader, rec)
468 SkMatrix newMatrix = *rec.fMatrix;
469 newMatrix.preConcat(shader.getLocalMatrix());
470 if (rec.fLocalMatrix) {
471 newMatrix.preConcat(*rec.fLocalMatrix);
473 // This (1,1) translation is due to WebKit's 1 based coordinates for the noise
474 // (as opposed to 0 based, usually). The same adjustment is in the setData() function.
475 fMatrix.setTranslate(-newMatrix.getTranslateX() + SK_Scalar1, -newMatrix.getTranslateY() + SK_Scalar1);
476 fPaintingData = SkNEW_ARGS(PaintingData, (shader.fTileSize, shader.fSeed, shader.fBaseFrequencyX, shader.fBaseFrequencyY, newMatrix));
479 SkPerlinNoiseShader::PerlinNoiseShaderContext::~PerlinNoiseShaderContext() {
480 SkDELETE(fPaintingData);
483 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan(
484 int x, int y, SkPMColor result[], int count) {
485 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
486 StitchData stitchData;
487 for (int i = 0; i < count; ++i) {
488 result[i] = shade(point, stitchData);
489 point.fX += SK_Scalar1;
493 void SkPerlinNoiseShader::PerlinNoiseShaderContext::shadeSpan16(
494 int x, int y, uint16_t result[], int count) {
495 SkPoint point = SkPoint::Make(SkIntToScalar(x), SkIntToScalar(y));
496 StitchData stitchData;
498 for (int i = 0; i < count; ++i) {
499 unsigned dither = DITHER_VALUE(x);
500 result[i] = SkDitherRGB32To565(shade(point, stitchData), dither);
502 point.fX += SK_Scalar1;
506 /////////////////////////////////////////////////////////////////////
510 #include "GrTBackendProcessorFactory.h"
512 class GrGLPerlinNoise : public GrGLFragmentProcessor {
514 GrGLPerlinNoise(const GrBackendProcessorFactory&,
516 virtual ~GrGLPerlinNoise() {}
518 virtual void emitCode(GrGLFPBuilder*,
519 const GrFragmentProcessor&,
520 const GrProcessorKey&,
521 const char* outputColor,
522 const char* inputColor,
523 const TransformedCoordsArray&,
524 const TextureSamplerArray&) SK_OVERRIDE;
526 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
528 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder* b);
532 GrGLProgramDataManager::UniformHandle fStitchDataUni;
533 SkPerlinNoiseShader::Type fType;
536 GrGLProgramDataManager::UniformHandle fBaseFrequencyUni;
537 GrGLProgramDataManager::UniformHandle fAlphaUni;
540 typedef GrGLFragmentProcessor INHERITED;
543 /////////////////////////////////////////////////////////////////////
545 class GrPerlinNoiseEffect : public GrFragmentProcessor {
547 static GrFragmentProcessor* Create(SkPerlinNoiseShader::Type type,
548 int numOctaves, bool stitchTiles,
549 SkPerlinNoiseShader::PaintingData* paintingData,
550 GrTexture* permutationsTexture, GrTexture* noiseTexture,
551 const SkMatrix& matrix, uint8_t alpha) {
552 return SkNEW_ARGS(GrPerlinNoiseEffect, (type, numOctaves, stitchTiles, paintingData,
553 permutationsTexture, noiseTexture, matrix, alpha));
556 virtual ~GrPerlinNoiseEffect() {
557 SkDELETE(fPaintingData);
560 static const char* Name() { return "PerlinNoise"; }
561 virtual const GrBackendFragmentProcessorFactory& getFactory() const SK_OVERRIDE {
562 return GrTBackendFragmentProcessorFactory<GrPerlinNoiseEffect>::getInstance();
564 const SkPerlinNoiseShader::StitchData& stitchData() const { return fPaintingData->fStitchDataInit; }
566 SkPerlinNoiseShader::Type type() const { return fType; }
567 bool stitchTiles() const { return fStitchTiles; }
568 const SkVector& baseFrequency() const { return fPaintingData->fBaseFrequency; }
569 int numOctaves() const { return fNumOctaves; }
570 const SkMatrix& matrix() const { return fCoordTransform.getMatrix(); }
571 uint8_t alpha() const { return fAlpha; }
573 typedef GrGLPerlinNoise GLProcessor;
576 virtual bool onIsEqual(const GrFragmentProcessor& sBase) const SK_OVERRIDE {
577 const GrPerlinNoiseEffect& s = sBase.cast<GrPerlinNoiseEffect>();
578 return fType == s.fType &&
579 fPaintingData->fBaseFrequency == s.fPaintingData->fBaseFrequency &&
580 fNumOctaves == s.fNumOctaves &&
581 fStitchTiles == s.fStitchTiles &&
582 fAlpha == s.fAlpha &&
583 fPaintingData->fStitchDataInit == s.fPaintingData->fStitchDataInit;
586 void onComputeInvariantOutput(InvariantOutput* inout) const SK_OVERRIDE {
587 inout->setToUnknown(InvariantOutput::kWillNot_ReadInput);
590 GrPerlinNoiseEffect(SkPerlinNoiseShader::Type type,
591 int numOctaves, bool stitchTiles,
592 SkPerlinNoiseShader::PaintingData* paintingData,
593 GrTexture* permutationsTexture, GrTexture* noiseTexture,
594 const SkMatrix& matrix, uint8_t alpha)
596 , fNumOctaves(numOctaves)
597 , fStitchTiles(stitchTiles)
599 , fPermutationsAccess(permutationsTexture)
600 , fNoiseAccess(noiseTexture)
601 , fPaintingData(paintingData) {
602 this->addTextureAccess(&fPermutationsAccess);
603 this->addTextureAccess(&fNoiseAccess);
604 fCoordTransform.reset(kLocal_GrCoordSet, matrix);
605 this->addCoordTransform(&fCoordTransform);
608 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
610 SkPerlinNoiseShader::Type fType;
611 GrCoordTransform fCoordTransform;
615 GrTextureAccess fPermutationsAccess;
616 GrTextureAccess fNoiseAccess;
617 SkPerlinNoiseShader::PaintingData *fPaintingData;
620 typedef GrFragmentProcessor INHERITED;
623 /////////////////////////////////////////////////////////////////////
624 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrPerlinNoiseEffect);
626 GrFragmentProcessor* GrPerlinNoiseEffect::TestCreate(SkRandom* random,
628 const GrDrawTargetCaps&,
630 int numOctaves = random->nextRangeU(2, 10);
631 bool stitchTiles = random->nextBool();
632 SkScalar seed = SkIntToScalar(random->nextU());
633 SkISize tileSize = SkISize::Make(random->nextRangeU(4, 4096), random->nextRangeU(4, 4096));
634 SkScalar baseFrequencyX = random->nextRangeScalar(0.01f,
636 SkScalar baseFrequencyY = random->nextRangeScalar(0.01f,
639 SkShader* shader = random->nextBool() ?
640 SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves, seed,
641 stitchTiles ? &tileSize : NULL) :
642 SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves, seed,
643 stitchTiles ? &tileSize : NULL);
647 GrFragmentProcessor* effect;
648 SkAssertResult(shader->asFragmentProcessor(context, paint, NULL, &paintColor, &effect));
655 GrGLPerlinNoise::GrGLPerlinNoise(const GrBackendProcessorFactory& factory,
656 const GrProcessor& processor)
657 : INHERITED (factory)
658 , fType(processor.cast<GrPerlinNoiseEffect>().type())
659 , fStitchTiles(processor.cast<GrPerlinNoiseEffect>().stitchTiles())
660 , fNumOctaves(processor.cast<GrPerlinNoiseEffect>().numOctaves()) {
663 void GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder,
664 const GrFragmentProcessor&,
665 const GrProcessorKey& key,
666 const char* outputColor,
667 const char* inputColor,
668 const TransformedCoordsArray& coords,
669 const TextureSamplerArray& samplers) {
670 sk_ignore_unused_variable(inputColor);
672 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
673 SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0);
675 fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
676 kVec2f_GrSLType, "baseFrequency");
677 const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni);
678 fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
679 kFloat_GrSLType, "alpha");
680 const char* alphaUni = builder->getUniformCStr(fAlphaUni);
682 const char* stitchDataUni = NULL;
684 fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
685 kVec2f_GrSLType, "stitchData");
686 stitchDataUni = builder->getUniformCStr(fStitchDataUni);
689 // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
690 const char* chanCoordR = "0.125";
691 const char* chanCoordG = "0.375";
692 const char* chanCoordB = "0.625";
693 const char* chanCoordA = "0.875";
694 const char* chanCoord = "chanCoord";
695 const char* stitchData = "stitchData";
696 const char* ratio = "ratio";
697 const char* noiseVec = "noiseVec";
698 const char* noiseSmooth = "noiseSmooth";
699 const char* floorVal = "floorVal";
700 const char* fractVal = "fractVal";
701 const char* uv = "uv";
702 const char* ab = "ab";
703 const char* latticeIdx = "latticeIdx";
704 const char* bcoords = "bcoords";
705 const char* lattice = "lattice";
706 const char* inc8bit = "0.00390625"; // 1.0 / 256.0
707 // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
708 // [-1,1] vector and perform a dot product between that vector and the provided vector.
709 const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
711 // Add noise function
712 static const GrGLShaderVar gPerlinNoiseArgs[] = {
713 GrGLShaderVar(chanCoord, kFloat_GrSLType),
714 GrGLShaderVar(noiseVec, kVec2f_GrSLType)
717 static const GrGLShaderVar gPerlinNoiseStitchArgs[] = {
718 GrGLShaderVar(chanCoord, kFloat_GrSLType),
719 GrGLShaderVar(noiseVec, kVec2f_GrSLType),
720 GrGLShaderVar(stitchData, kVec2f_GrSLType)
725 noiseCode.appendf("\tvec4 %s;\n", floorVal);
726 noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
727 noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
728 noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
730 // smooth curve : t * t * (3 - 2 * t)
731 noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
732 noiseSmooth, fractVal, fractVal, fractVal);
734 // Adjust frequencies if we're stitching tiles
736 noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
737 floorVal, stitchData, floorVal, stitchData);
738 noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
739 floorVal, stitchData, floorVal, stitchData);
740 noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
741 floorVal, stitchData, floorVal, stitchData);
742 noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
743 floorVal, stitchData, floorVal, stitchData);
746 // Get texture coordinates and normalize
747 noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
750 // Get permutation for x
752 SkString xCoords("");
753 xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
755 noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
756 fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
757 noiseCode.append(".r;");
760 // Get permutation for x + 1
762 SkString xCoords("");
763 xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
765 noiseCode.appendf("\n\t%s.y = ", latticeIdx);
766 fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
767 noiseCode.append(".r;");
770 #if defined(SK_BUILD_FOR_ANDROID)
771 // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3).
772 // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit
773 // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725
774 // (or 0.484368 here). The following rounding operation prevents these precision issues from
775 // affecting the result of the noise by making sure that we only have multiples of 1/255.
776 // (Note that 1/255 is about 0.003921569, which is the value used here).
777 noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);",
778 latticeIdx, latticeIdx);
781 // Get (x,y) coordinates with the permutated x
782 noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
784 noiseCode.appendf("\n\n\tvec2 %s;", uv);
785 // Compute u, at offset (0,0)
787 SkString latticeCoords("");
788 latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
789 noiseCode.appendf("\n\tvec4 %s = ", lattice);
790 fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
792 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
793 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
796 noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal);
797 // Compute v, at offset (-1,0)
799 SkString latticeCoords("");
800 latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
801 noiseCode.append("\n\tlattice = ");
802 fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
804 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
805 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
808 // Compute 'a' as a linear interpolation of 'u' and 'v'
809 noiseCode.appendf("\n\tvec2 %s;", ab);
810 noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
812 noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal);
813 // Compute v, at offset (-1,-1)
815 SkString latticeCoords("");
816 latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
817 noiseCode.append("\n\tlattice = ");
818 fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
820 noiseCode.appendf(".bgra;\n\t%s.y = ", uv);
821 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
824 noiseCode.appendf("\n\t%s.x += 1.0;", fractVal);
825 // Compute u, at offset (0,-1)
827 SkString latticeCoords("");
828 latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
829 noiseCode.append("\n\tlattice = ");
830 fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
832 noiseCode.appendf(".bgra;\n\t%s.x = ", uv);
833 noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
836 // Compute 'b' as a linear interpolation of 'u' and 'v'
837 noiseCode.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
838 // Compute the noise as a linear interpolation of 'a' and 'b'
839 noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
841 SkString noiseFuncName;
843 fsBuilder->emitFunction(kFloat_GrSLType,
844 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs),
845 gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName);
847 fsBuilder->emitFunction(kFloat_GrSLType,
848 "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs),
849 gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName);
852 // There are rounding errors if the floor operation is not performed here
853 fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;",
854 noiseVec, vCoords.c_str(), baseFrequencyUni);
856 // Clear the color accumulator
857 fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor);
860 // Set up TurbulenceInitial stitch values.
861 fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni);
864 fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio);
866 // Loop over all octaves
867 fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
869 fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor);
870 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
871 fsBuilder->codeAppend("abs(");
874 fsBuilder->codeAppendf(
875 "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
876 "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
877 noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData,
878 noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData,
879 noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData,
880 noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData);
882 fsBuilder->codeAppendf(
883 "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
884 "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
885 noiseFuncName.c_str(), chanCoordR, noiseVec,
886 noiseFuncName.c_str(), chanCoordG, noiseVec,
887 noiseFuncName.c_str(), chanCoordB, noiseVec,
888 noiseFuncName.c_str(), chanCoordA, noiseVec);
890 if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
891 fsBuilder->codeAppendf(")"); // end of "abs("
893 fsBuilder->codeAppendf(" * %s;", ratio);
895 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
896 fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio);
899 fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData);
901 fsBuilder->codeAppend("\n\t\t}"); // end of the for loop on octaves
903 if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
904 // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
905 // by fractalNoise and (turbulenceFunctionResult) by turbulence.
906 fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
909 fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni);
912 fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
914 // Pre-multiply the result
915 fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
916 outputColor, outputColor, outputColor, outputColor);
919 void GrGLPerlinNoise::GenKey(const GrProcessor& processor, const GrGLCaps&,
920 GrProcessorKeyBuilder* b) {
921 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
923 uint32_t key = turbulence.numOctaves();
925 key = key << 3; // Make room for next 3 bits
927 switch (turbulence.type()) {
928 case SkPerlinNoiseShader::kFractalNoise_Type:
931 case SkPerlinNoiseShader::kTurbulence_Type:
939 if (turbulence.stitchTiles()) {
940 key |= 0x4; // Flip the 3rd bit if tile stitching is on
946 void GrGLPerlinNoise::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
947 INHERITED::setData(pdman, processor);
949 const GrPerlinNoiseEffect& turbulence = processor.cast<GrPerlinNoiseEffect>();
951 const SkVector& baseFrequency = turbulence.baseFrequency();
952 pdman.set2f(fBaseFrequencyUni, baseFrequency.fX, baseFrequency.fY);
953 pdman.set1f(fAlphaUni, SkScalarDiv(SkIntToScalar(turbulence.alpha()), SkIntToScalar(255)));
955 if (turbulence.stitchTiles()) {
956 const SkPerlinNoiseShader::StitchData& stitchData = turbulence.stitchData();
957 pdman.set2f(fStitchDataUni, SkIntToScalar(stitchData.fWidth),
958 SkIntToScalar(stitchData.fHeight));
962 /////////////////////////////////////////////////////////////////////
964 bool SkPerlinNoiseShader::asFragmentProcessor(GrContext* context, const SkPaint& paint,
965 const SkMatrix* externalLocalMatrix,
966 GrColor* paintColor, GrFragmentProcessor** fp) const {
969 *paintColor = SkColor2GrColorJustAlpha(paint.getColor());
971 SkMatrix localMatrix = this->getLocalMatrix();
972 if (externalLocalMatrix) {
973 localMatrix.preConcat(*externalLocalMatrix);
976 SkMatrix matrix = context->getMatrix();
977 matrix.preConcat(localMatrix);
979 if (0 == fNumOctaves) {
980 SkColor clearColor = 0;
981 if (kFractalNoise_Type == fType) {
982 clearColor = SkColorSetARGB(paint.getAlpha() / 2, 127, 127, 127);
984 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(
985 clearColor, SkXfermode::kSrc_Mode));
986 *fp = cf->asFragmentProcessor(context);
990 // Either we don't stitch tiles, either we have a valid tile size
991 SkASSERT(!fStitchTiles || !fTileSize.isEmpty());
993 SkPerlinNoiseShader::PaintingData* paintingData =
994 SkNEW_ARGS(PaintingData, (fTileSize, fSeed, fBaseFrequencyX, fBaseFrequencyY, matrix));
995 SkAutoTUnref<GrTexture> permutationsTexture(
996 GrRefCachedBitmapTexture(context, paintingData->getPermutationsBitmap(), NULL));
997 SkAutoTUnref<GrTexture> noiseTexture(
998 GrRefCachedBitmapTexture(context, paintingData->getNoiseBitmap(), NULL));
1000 SkMatrix m = context->getMatrix();
1001 m.setTranslateX(-localMatrix.getTranslateX() + SK_Scalar1);
1002 m.setTranslateY(-localMatrix.getTranslateY() + SK_Scalar1);
1003 if ((permutationsTexture) && (noiseTexture)) {
1004 *fp = GrPerlinNoiseEffect::Create(fType,
1008 permutationsTexture, noiseTexture,
1009 m, paint.getAlpha());
1011 SkDELETE(paintingData);
1019 bool SkPerlinNoiseShader::asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*, GrColor*,
1020 GrFragmentProcessor**) const {
1021 SkDEBUGFAIL("Should not call in GPU-less build");
1027 #ifndef SK_IGNORE_TO_STRING
1028 void SkPerlinNoiseShader::toString(SkString* str) const {
1029 str->append("SkPerlinNoiseShader: (");
1031 str->append("type: ");
1033 case kFractalNoise_Type:
1034 str->append("\"fractal noise\"");
1036 case kTurbulence_Type:
1037 str->append("\"turbulence\"");
1040 str->append("\"unknown\"");
1043 str->append(" base frequency: (");
1044 str->appendScalar(fBaseFrequencyX);
1046 str->appendScalar(fBaseFrequencyY);
1047 str->append(") number of octaves: ");
1048 str->appendS32(fNumOctaves);
1049 str->append(" seed: ");
1050 str->appendScalar(fSeed);
1051 str->append(" stitch tiles: ");
1052 str->append(fStitchTiles ? "true " : "false ");
1054 this->INHERITED::toString(str);