float fractal(vec2 p) { float v = 0.5; v += noise2D(p*16.); v*=.5; v += noise2D(p*8.); v*=.5; v += noise2D(p*4.); v*=.5; v += noise2D(p*2.); v*=.5; v += noise2D(p*1.); v*=.5; return v; }
T smoothedNoise2D(const int x, const int y) { T corners = (noise2D(x-1, y-1) + noise2D(x+1, y-1) + noise2D(x-1, y+1) + noise2D(x+1, y+1)) / 16; T sides = ( noise2D(x-1, y) + noise2D(x+1, y) + noise2D(x, y-1) + noise2D(x, y+1)) / 8; T center = noise2D(x, y) / 4; return corners + sides + center; }
double Perlin::coherentNoise2D(double x, double y) { double sum = 0; double p = 1; int f = 1; int i = 0; for(; i < octaves ; i++) { sum += p * noise2D(x * f, y * f); p *= persistence; f *= 2; } return sum * (1 - persistence) / (1 - p); }
SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::calculateTurbulenceValueForPoint( int channel, StitchData& stitchData, const SkPoint& point) const { const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); if (perlinNoiseShader.fStitchTiles) { // Set up TurbulenceInitial stitch values. stitchData = fPaintingData->fStitchDataInit; } SkScalar turbulenceFunctionResult = 0; SkPoint noiseVector(SkPoint::Make(SkScalarMul(point.x(), fPaintingData->fBaseFrequency.fX), SkScalarMul(point.y(), fPaintingData->fBaseFrequency.fY))); SkScalar ratio = SK_Scalar1; for (int octave = 0; octave < perlinNoiseShader.fNumOctaves; ++octave) { SkScalar noise = noise2D(channel, stitchData, noiseVector); SkScalar numer = (perlinNoiseShader.fType == kFractalNoise_Type) ? noise : SkScalarAbs(noise); turbulenceFunctionResult += numer / ratio; noiseVector.fX *= 2; noiseVector.fY *= 2; ratio *= 2; if (perlinNoiseShader.fStitchTiles) { // Update stitch values stitchData.fWidth *= 2; stitchData.fWrapX = stitchData.fWidth + kPerlinNoise; stitchData.fHeight *= 2; stitchData.fWrapY = stitchData.fHeight + kPerlinNoise; } } // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2 // by fractalNoise and (turbulenceFunctionResult) by turbulence. if (perlinNoiseShader.fType == kFractalNoise_Type) { turbulenceFunctionResult = SkScalarMul(turbulenceFunctionResult, SK_ScalarHalf) + SK_ScalarHalf; } if (channel == 3) { // Scale alpha by paint value turbulenceFunctionResult *= SkIntToScalar(getPaintAlpha()) / 255; } // Clamp result return SkScalarPin(turbulenceFunctionResult, 0, SK_Scalar1); }
unsigned char FETurbulence::calculateTurbulenceValueForPoint(int channel, PaintingData& paintingData, const FloatPoint& point) { float tileWidth = paintingData.filterSize.width(); ASSERT(tileWidth > 0); float tileHeight = paintingData.filterSize.height(); ASSERT(tileHeight > 0); // Adjust the base frequencies if necessary for stitching. if (m_stitchTiles) { // When stitching tiled turbulence, the frequencies must be adjusted // so that the tile borders will be continuous. if (m_baseFrequencyX) { float lowFrequency = floorf(tileWidth * m_baseFrequencyX) / tileWidth; float highFrequency = ceilf(tileWidth * m_baseFrequencyX) / tileWidth; // BaseFrequency should be non-negative according to the standard. if (m_baseFrequencyX / lowFrequency < highFrequency / m_baseFrequencyX) m_baseFrequencyX = lowFrequency; else m_baseFrequencyX = highFrequency; } if (m_baseFrequencyY) { float lowFrequency = floorf(tileHeight * m_baseFrequencyY) / tileHeight; float highFrequency = ceilf(tileHeight * m_baseFrequencyY) / tileHeight; if (m_baseFrequencyY / lowFrequency < highFrequency / m_baseFrequencyY) m_baseFrequencyY = lowFrequency; else m_baseFrequencyY = highFrequency; } // Set up TurbulenceInitial stitch values. paintingData.width = roundf(tileWidth * m_baseFrequencyX); paintingData.wrapX = s_perlinNoise + paintingData.width; paintingData.height = roundf(tileHeight * m_baseFrequencyY); paintingData.wrapY = s_perlinNoise + paintingData.height; } float turbulenceFunctionResult = 0; FloatPoint noiseVector(point.x() * m_baseFrequencyX, point.y() * m_baseFrequencyY); float ratio = 1; for (int octave = 0; octave < m_numOctaves; ++octave) { if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) turbulenceFunctionResult += noise2D(channel, paintingData, noiseVector) / ratio; else turbulenceFunctionResult += fabsf(noise2D(channel, paintingData, noiseVector)) / ratio; noiseVector.setX(noiseVector.x() * 2); noiseVector.setY(noiseVector.y() * 2); ratio *= 2; if (m_stitchTiles) { // Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and // adding it afterward simplifies to subtracting it once. paintingData.width *= 2; paintingData.wrapX = 2 * paintingData.wrapX - s_perlinNoise; paintingData.height *= 2; paintingData.wrapY = 2 * paintingData.wrapY - s_perlinNoise; } } // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult * 255) + 255) / 2 by fractalNoise // and (turbulenceFunctionResult * 255) by turbulence. if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) turbulenceFunctionResult = turbulenceFunctionResult * 0.5f + 0.5f; // Clamp result turbulenceFunctionResult = std::max(std::min(turbulenceFunctionResult, 1.f), 0.f); return static_cast<unsigned char>(turbulenceFunctionResult * 255); }
float perlinNoise::smoothNoise2D(float x,float y){ float corners = (noise2D(x-1, y-1) + noise2D(x+1, y-1) + noise2D(x-1, y+1) + noise2D(x+1, y+1)) / 16; float sides = (noise2D(x-1, y) + noise2D(x+1, y) + noise2D(x, y-1) + noise2D(x, y+1)) / 8; float center = noise2D(x, y) / 4; return corners + sides + center; }