aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expectations/gm/ignored-tests.txt4
-rw-r--r--gm/perlinnoise.cpp33
-rw-r--r--src/effects/SkPerlinNoiseShader.cpp77
3 files changed, 68 insertions, 46 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index 573593bca6..9d6ce3ee31 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -78,3 +78,7 @@ dashcubics
# dandov: Fix for bitmap shader by taking into account if the bitmap is alpha only
# https://codereview.chromium.org/318923005/
bitmapshaders
+
+# Added by senorblanco for https://codereview.chromium.org/332523006/
+# Needs rebaseline for modified test cases
+perlinnoise
diff --git a/gm/perlinnoise.cpp b/gm/perlinnoise.cpp
index ee58f6f5aa..b69b7d0476 100644
--- a/gm/perlinnoise.cpp
+++ b/gm/perlinnoise.cpp
@@ -24,13 +24,11 @@ protected:
return SkISize::Make(200, 500);
}
- void drawClippedRect(SkCanvas* canvas, int x, int y, const SkPaint& paint) {
+ void drawRect(SkCanvas* canvas, int x, int y, const SkPaint& paint, const SkISize& size) {
canvas->save();
- canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
- SkIntToScalar(fSize.width()), SkIntToScalar(fSize.height())));
- SkRect r = SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
- SkIntToScalar(fSize.width()),
- SkIntToScalar(fSize.height()));
+ canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
+ SkRect r = SkRect::MakeWH(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()));
canvas->drawRect(r, paint);
canvas->restore();
}
@@ -38,14 +36,25 @@ protected:
void test(SkCanvas* canvas, int x, int y, SkPerlinNoiseShader::Type type,
float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed,
bool stitchTiles) {
+ SkISize tileSize = SkISize::Make(fSize.width() / 2, fSize.height() / 2);
SkShader* shader = (type == SkPerlinNoiseShader::kFractalNoise_Type) ?
SkPerlinNoiseShader::CreateFractalNoise(baseFrequencyX, baseFrequencyY, numOctaves,
- seed, stitchTiles ? &fSize : NULL) :
+ seed, stitchTiles ? &tileSize : NULL) :
SkPerlinNoiseShader::CreateTurbulence(baseFrequencyX, baseFrequencyY, numOctaves,
- seed, stitchTiles ? &fSize : NULL);
+ seed, stitchTiles ? &tileSize : NULL);
SkPaint paint;
paint.setShader(shader)->unref();
- drawClippedRect(canvas, x, y, paint);
+ if (stitchTiles) {
+ drawRect(canvas, x, y, paint, tileSize);
+ x += tileSize.width();
+ drawRect(canvas, x, y, paint, tileSize);
+ y += tileSize.width();
+ drawRect(canvas, x, y, paint, tileSize);
+ x -= tileSize.width();
+ drawRect(canvas, x, y, paint, tileSize);
+ } else {
+ drawRect(canvas, x, y, paint, fSize);
+ }
}
virtual void onDraw(SkCanvas* canvas) {
@@ -58,10 +67,10 @@ protected:
test(canvas, 0, 100, SkPerlinNoiseShader::kFractalNoise_Type,
0.1f, 0.1f, 2, 0, false);
test(canvas, 100, 100, SkPerlinNoiseShader::kFractalNoise_Type,
- 0.2f, 0.4f, 5, 0, true);
+ 0.05f, 0.1f, 1, 0, true);
test(canvas, 0, 200, SkPerlinNoiseShader::kTurbulence_Type,
- 0.1f, 0.1f, 2, 0, true);
+ 0.1f, 0.1f, 1, 0, true);
test(canvas, 100, 200, SkPerlinNoiseShader::kTurbulence_Type,
0.2f, 0.4f, 5, 0, false);
@@ -75,7 +84,7 @@ protected:
test(canvas, 0, 400, SkPerlinNoiseShader::kFractalNoise_Type,
0.1f, 0.1f, 2, 0, false);
test(canvas, 100, 400, SkPerlinNoiseShader::kFractalNoise_Type,
- 0.2f, 0.4f, 5, 0, true);
+ 0.1f, 0.05f, 1, 0, true);
}
private:
diff --git a/src/effects/SkPerlinNoiseShader.cpp b/src/effects/SkPerlinNoiseShader.cpp
index bc24061d28..c230c2d648 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);