| Index: src/effects/SkPerlinNoiseShader.cpp
|
| diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
|
| index bc24061d281448420216c88a3171bd72e63a0c4b..c230c2d6482bad6a4e16a2d1750a7f226b790ef7 100644
|
| --- a/src/effects/SkPerlinNoiseShader.cpp
|
| +++ b/src/effects/SkPerlinNoiseShader.cpp
|
| @@ -39,9 +39,6 @@ inline int checkNoise(int noiseValue, int limitValue, int newValue) {
|
| if (noiseValue >= limitValue) {
|
| noiseValue -= newValue;
|
| }
|
| - if (noiseValue >= limitValue - 1) {
|
| - noiseValue -= newValue - 1;
|
| - }
|
| return noiseValue;
|
| }
|
|
|
| @@ -320,12 +317,14 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
| 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());
|
| @@ -338,28 +337,36 @@ SkScalar SkPerlinNoiseShader::PerlinNoiseShaderContext::noise2D(
|
| 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;
|
| - int latticeIndex =
|
| - paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue] +
|
| - noiseY.noisePositionIntegerValue;
|
| - int nextLatticeIndex =
|
| - paintingData.fLatticeSelector[(noiseX.noisePositionIntegerValue + 1) & kBlockMask] +
|
| - noiseY.noisePositionIntegerValue;
|
| + noiseX.nextNoisePositionIntegerValue &= kBlockMask;
|
| + noiseY.nextNoisePositionIntegerValue &= kBlockMask;
|
| + int i =
|
| + paintingData.fLatticeSelector[noiseX.noisePositionIntegerValue];
|
| + int j =
|
| + paintingData.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 = paintingData.fGradient[channel][latticeIndex & kBlockMask].dot(fractionValue);
|
| + u = paintingData.fGradient[channel][b00].dot(fractionValue);
|
| fractionValue.fX -= SK_Scalar1; // Offset (-1,0)
|
| - v = paintingData.fGradient[channel][nextLatticeIndex & kBlockMask].dot(fractionValue);
|
| + v = paintingData.fGradient[channel][b10].dot(fractionValue);
|
| SkScalar a = SkScalarInterp(u, v, sx);
|
| fractionValue.fY -= SK_Scalar1; // Offset (-1,-1)
|
| - v = paintingData.fGradient[channel][(nextLatticeIndex + 1) & kBlockMask].dot(fractionValue);
|
| + v = paintingData.fGradient[channel][b11].dot(fractionValue);
|
| fractionValue.fX = noiseX.noisePositionFractionValue; // Offset (0,-1)
|
| - u = paintingData.fGradient[channel][(latticeIndex + 1) & kBlockMask].dot(fractionValue);
|
| + u = paintingData.fGradient[channel][b01].dot(fractionValue);
|
| SkScalar b = SkScalarInterp(u, v, sx);
|
| return SkScalarInterp(a, b, sy);
|
| }
|
| @@ -989,13 +996,14 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| const char* chanCoord = "chanCoord";
|
| const char* stitchData = "stitchData";
|
| const char* ratio = "ratio";
|
| - const char* noiseXY = "noiseXY";
|
| const char* noiseVec = "noiseVec";
|
| const char* noiseSmooth = "noiseSmooth";
|
| + const char* floorVal = "floorVal";
|
| const char* fractVal = "fractVal";
|
| const char* uv = "uv";
|
| const char* ab = "ab";
|
| const char* latticeIdx = "latticeIdx";
|
| + const char* bcoords = "bcoords";
|
| const char* lattice = "lattice";
|
| const char* inc8bit = "0.00390625"; // 1.0 / 256.0
|
| // This is the math to convert the two 16bit integer packed into rgba 8 bit input into a
|
| @@ -1016,32 +1024,35 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
|
|
| SkString noiseCode;
|
|
|
| - noiseCode.appendf("\tvec4 %s = vec4(floor(%s), fract(%s));", noiseXY, noiseVec, noiseVec);
|
| + noiseCode.appendf("\tvec4 %s;\n", floorVal);
|
| + noiseCode.appendf("\t%s.xy = floor(%s);\n", floorVal, noiseVec);
|
| + noiseCode.appendf("\t%s.zw = %s.xy + vec2(1.0);\n", floorVal, floorVal);
|
| + noiseCode.appendf("\tvec2 %s = fract(%s);\n", fractVal, noiseVec);
|
|
|
| // smooth curve : t * t * (3 - 2 * t)
|
| - noiseCode.appendf("\n\tvec2 %s = %s.zw * %s.zw * (vec2(3.0) - vec2(2.0) * %s.zw);",
|
| - noiseSmooth, noiseXY, noiseXY, noiseXY);
|
| + noiseCode.appendf("\n\tvec2 %s = %s * %s * (vec2(3.0) - vec2(2.0) * %s);",
|
| + noiseSmooth, fractVal, fractVal, fractVal);
|
|
|
| // Adjust frequencies if we're stitching tiles
|
| if (fStitchTiles) {
|
| noiseCode.appendf("\n\tif(%s.x >= %s.x) { %s.x -= %s.x; }",
|
| - noiseXY, stitchData, noiseXY, stitchData);
|
| - noiseCode.appendf("\n\tif(%s.x >= (%s.x - 1.0)) { %s.x -= (%s.x - 1.0); }",
|
| - noiseXY, stitchData, noiseXY, stitchData);
|
| + floorVal, stitchData, floorVal, stitchData);
|
| noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }",
|
| - noiseXY, stitchData, noiseXY, stitchData);
|
| - noiseCode.appendf("\n\tif(%s.y >= (%s.y - 1.0)) { %s.y -= (%s.y - 1.0); }",
|
| - noiseXY, stitchData, noiseXY, stitchData);
|
| + floorVal, stitchData, floorVal, stitchData);
|
| + noiseCode.appendf("\n\tif(%s.z >= %s.x) { %s.z -= %s.x; }",
|
| + floorVal, stitchData, floorVal, stitchData);
|
| + noiseCode.appendf("\n\tif(%s.w >= %s.y) { %s.w -= %s.y; }",
|
| + floorVal, stitchData, floorVal, stitchData);
|
| }
|
|
|
| // Get texture coordinates and normalize
|
| - noiseCode.appendf("\n\t%s.xy = fract(floor(mod(%s.xy, 256.0)) / vec2(256.0));\n",
|
| - noiseXY, noiseXY);
|
| + noiseCode.appendf("\n\t%s = fract(floor(mod(%s, 256.0)) / vec4(256.0));\n",
|
| + floorVal, floorVal);
|
|
|
| // Get permutation for x
|
| {
|
| SkString xCoords("");
|
| - xCoords.appendf("vec2(%s.x, 0.5)", noiseXY);
|
| + xCoords.appendf("vec2(%s.x, 0.5)", floorVal);
|
|
|
| noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
|
| builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
|
| @@ -1051,7 +1062,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| // Get permutation for x + 1
|
| {
|
| SkString xCoords("");
|
| - xCoords.appendf("vec2(fract(%s.x + %s), 0.5)", noiseXY, inc8bit);
|
| + xCoords.appendf("vec2(%s.z, 0.5)", floorVal);
|
|
|
| noiseCode.appendf("\n\t%s.y = ", latticeIdx);
|
| builder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
|
| @@ -1070,15 +1081,13 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| #endif
|
|
|
| // Get (x,y) coordinates with the permutated x
|
| - noiseCode.appendf("\n\t%s = fract(%s + %s.yy);", latticeIdx, latticeIdx, noiseXY);
|
| -
|
| - noiseCode.appendf("\n\tvec2 %s = %s.zw;", fractVal, noiseXY);
|
| + noiseCode.appendf("\n\tvec4 %s = fract(%s.xyxy + %s.yyww);", bcoords, latticeIdx, floorVal);
|
|
|
| noiseCode.appendf("\n\n\tvec2 %s;", uv);
|
| // Compute u, at offset (0,0)
|
| {
|
| SkString latticeCoords("");
|
| - latticeCoords.appendf("vec2(%s.x, %s)", latticeIdx, chanCoord);
|
| + latticeCoords.appendf("vec2(%s.x, %s)", bcoords, chanCoord);
|
| noiseCode.appendf("\n\tvec4 %s = ", lattice);
|
| builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
| kVec2f_GrSLType);
|
| @@ -1090,7 +1099,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| // Compute v, at offset (-1,0)
|
| {
|
| SkString latticeCoords("");
|
| - latticeCoords.appendf("vec2(%s.y, %s)", latticeIdx, chanCoord);
|
| + latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord);
|
| noiseCode.append("\n\tlattice = ");
|
| builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
| kVec2f_GrSLType);
|
| @@ -1106,7 +1115,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| // Compute v, at offset (-1,-1)
|
| {
|
| SkString latticeCoords("");
|
| - latticeCoords.appendf("vec2(fract(%s.y + %s), %s)", latticeIdx, inc8bit, chanCoord);
|
| + latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord);
|
| noiseCode.append("\n\tlattice = ");
|
| builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
| kVec2f_GrSLType);
|
| @@ -1118,7 +1127,7 @@ void GrGLPerlinNoise::emitCode(GrGLShaderBuilder* builder,
|
| // Compute u, at offset (0,-1)
|
| {
|
| SkString latticeCoords("");
|
| - latticeCoords.appendf("vec2(fract(%s.x + %s), %s)", latticeIdx, inc8bit, chanCoord);
|
| + latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord);
|
| noiseCode.append("\n\tlattice = ");
|
| builder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(),
|
| kVec2f_GrSLType);
|
|
|