SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D( int channel, const StitchData& stitchData, const SkPoint& noiseVector) const { struct Noise { int noisePositionIntegerValue; int nextNoisePositionIntegerValue; SkScalar noisePositionFractionValue; Noise(SkScalar component) { SkScalar position = component + kPerlinNoise; noisePositionIntegerValue = SkScalarFloorToInt(position); noisePositionFractionValue = position - SkIntToScalar(noisePositionIntegerValue); nextNoisePositionIntegerValue = noisePositionIntegerValue + 1; } }; Noise noiseX(noiseVector.x()); Noise noiseY(noiseVector.y()); SkScalar u, v; const SkPerlinNoiseShader& perlinNoiseShader = static_cast<const SkPerlinNoiseShader&>(fShader); // If stitching, adjust lattice points accordingly. if (perlinNoiseShader.fStitchTiles) { noiseX.noisePositionIntegerValue = checkNoise(noiseX.noisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); noiseY.noisePositionIntegerValue = checkNoise(noiseY.noisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); noiseX.nextNoisePositionIntegerValue = checkNoise(noiseX.nextNoisePositionIntegerValue, stitchData.fWrapX, stitchData.fWidth); noiseY.nextNoisePositionIntegerValue = checkNoise(noiseY.nextNoisePositionIntegerValue, stitchData.fWrapY, stitchData.fHeight); } noiseX.noisePositionIntegerValue &= kBlockMask; noiseY.noisePositionIntegerValue &= kBlockMask; noiseX.nextNoisePositionIntegerValue &= kBlockMask; noiseY.nextNoisePositionIntegerValue &= kBlockMask; int i = fPaintingData->fLatticeSelector[noiseX.noisePositionIntegerValue]; int j = fPaintingData->fLatticeSelector[noiseX.nextNoisePositionIntegerValue]; int b00 = (i + noiseY.noisePositionIntegerValue) & kBlockMask; int b10 = (j + noiseY.noisePositionIntegerValue) & kBlockMask; int b01 = (i + noiseY.nextNoisePositionIntegerValue) & kBlockMask; int b11 = (j + noiseY.nextNoisePositionIntegerValue) & kBlockMask; SkScalar sx = smoothCurve(noiseX.noisePositionFractionValue); SkScalar sy = smoothCurve(noiseY.noisePositionFractionValue); // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement SkPoint fractionValue = SkPoint::Make(noiseX.noisePositionFractionValue, noiseY.noisePositionFractionValue); // Offset (0,0) u = fPaintingData->fGradient[channel][b00].dot(fractionValue); fractionValue.fX -= SK_Scalar1; // Offset (-1,0) v = fPaintingData->fGradient[channel][b10].dot(fractionValue); SkScalar a = SkScalarInterp(u, v, sx); fractionValue.fY -= SK_Scalar1; // Offset (-1,-1) v = fPaintingData->fGradient[channel][b11].dot(fractionValue); fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1) u = fPaintingData->fGradient[channel][b01].dot(fractionValue); SkScalar b = SkScalarInterp(u, v, sx); return SkScalarInterp(a, b, sy); }
float FETurbulence::noise2D(int channel, PaintingData& paintingData, const FloatPoint& noiseVector) { struct Noise { int noisePositionIntegerValue; float noisePositionFractionValue; Noise(float component) { float position = component + s_perlinNoise; noisePositionIntegerValue = static_cast<int>(position); noisePositionFractionValue = position - noisePositionIntegerValue; } }; Noise noiseX(noiseVector.x()); Noise noiseY(noiseVector.y()); float* q; float sx, sy, a, b, u, v; // If stitching, adjust lattice points accordingly. if (m_stitchTiles) { checkNoise(noiseX.noisePositionIntegerValue, paintingData.wrapX, paintingData.width); checkNoise(noiseY.noisePositionIntegerValue, paintingData.wrapY, paintingData.height); } noiseX.noisePositionIntegerValue &= s_blockMask; noiseY.noisePositionIntegerValue &= s_blockMask; int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue]; int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask]; sx = smoothCurve(noiseX.noisePositionFractionValue); sy = smoothCurve(noiseY.noisePositionFractionValue); // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement. int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue]; q = paintingData.gradient[channel][temp]; u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1]; temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue]; q = paintingData.gradient[channel][temp]; v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1]; a = linearInterpolation(sx, u, v); temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1]; q = paintingData.gradient[channel][temp]; u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1]; q = paintingData.gradient[channel][temp]; v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; b = linearInterpolation(sx, u, v); return linearInterpolation(sy, a, b); }