Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(208)

Unified Diff: src/effects/SkPerlinNoiseShader.cpp

Issue 15753005: Fixed gpu perlin noise on Windows (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/effects/SkPerlinNoiseShader.cpp
===================================================================
--- src/effects/SkPerlinNoiseShader.cpp (revision 9474)
+++ src/effects/SkPerlinNoiseShader.cpp (working copy)
@@ -494,7 +494,7 @@
/////////////////////////////////////////////////////////////////////
-#if SK_SUPPORT_GPU && !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_WIN)
+#if SK_SUPPORT_GPU && !defined(SK_BUILD_FOR_ANDROID)
// CPU noise is faster on Android, so the GPU implementation is only for desktop
#include "GrTBackendEffectFactory.h"
@@ -986,13 +986,16 @@
stitchDataUni = builder->getUniformCStr(fStitchDataUni);
}
- const char* chanCoords = "chanCoords";
+ // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
+ const char* chanCoordR = "0.125";
+ const char* chanCoordG = "0.375";
+ const char* chanCoordB = "0.625";
+ const char* chanCoordA = "0.875";
+ const char* chanCoord = "chanCoord";
const char* stitchData = "stitchData";
const char* ratio = "ratio";
- const char* noise = "noise";
const char* noiseXY = "noiseXY";
const char* noiseVec = "noiseVec";
- const char* noiseVecIni = "noiseVecIni";
const char* noiseSmooth = "noiseSmooth";
const char* fractVal = "fractVal";
const char* uv = "uv";
@@ -1005,61 +1008,52 @@
// [-1,1] vector and perform a dot product between that vector and the provided vector.
const char* dotLattice = "dot(((%s.ga + %s.rb * vec2(%s)) * vec2(2.0) - vec2(1.0)), %s);";
- // There are 4 lines, so the center of each line is 1/8, 3/8, 5/8 and 7/8
- builder->fsCodeAppendf("\t\tconst vec4 %s = vec4(0.125, 0.375, 0.625, 0.875);", chanCoords);
+ // Add noise function
+ static const GrGLShaderVar perlinnoise_Args[] = {
bsalomon 2013/06/10 13:39:25 We already have two conventions for static const g
+ GrGLShaderVar(chanCoord, kFloat_GrSLType),
+ GrGLShaderVar(noiseVec, kVec2f_GrSLType)
+ };
- // There are rounding errors if the floor operation is not performed here
- builder->fsCodeAppendf("\t\tvec2 %s = floor((%s*vec3(%s, 1.0)).xy) * %s;",
- noiseVecIni, invMatrixUni, vCoords, baseFrequencyUni);
+ static const GrGLShaderVar perlinnoise_stitch_Args[] = {
+ GrGLShaderVar(chanCoord, kFloat_GrSLType),
+ GrGLShaderVar(noiseVec, kVec2f_GrSLType),
+ GrGLShaderVar(stitchData, kVec4f_GrSLType)
+ };
- // Loop over the 4 channels
- builder->fsCodeAppend("\t\tfor (int channel = 3; channel >= 0; --channel) {");
+ SkString noise_code;
bsalomon 2013/06/10 13:39:25 localVarsAreLikeThis.
- if (fStitchTiles) {
- // Set up TurbulenceInitial stitch values.
- builder->fsCodeAppendf("\t\tvec4 %s = %s;", stitchData, stitchDataUni);
- }
+ noise_code.appendf(
+ "\tvec4 %s = vec4(floor(%s) + vec2(%s), fract(%s));",
+ noiseXY, noiseVec, perlinNoise, noiseVec);
- builder->fsCodeAppendf("\t\t%s[channel] = 0.0;", outputColor);
-
- builder->fsCodeAppendf("\t\tfloat %s = 1.0;", ratio);
- builder->fsCodeAppendf("\t\tvec2 %s = %s;", noiseVec, noiseVecIni);
-
- // Loop over all octaves
- builder->fsCodeAppendf("\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
-
- builder->fsCodeAppendf("\t\tvec4 %s = vec4(floor(%s) + vec2(%s), fract(%s));",
- noiseXY, noiseVec, perlinNoise, noiseVec);
-
// smooth curve : t * t * (3 - 2 * t)
- builder->fsCodeAppendf("\t\tvec2 %s = %s.zw * %s.zw * (vec2(3.0) - vec2(2.0) * %s.zw);",
- noiseSmooth, noiseXY, noiseXY, noiseXY);
+ noise_code.appendf("\n\tvec2 %s = %s.zw * %s.zw * (vec2(3.0) - vec2(2.0) * %s.zw);",
+ noiseSmooth, noiseXY, noiseXY, noiseXY);
// Adjust frequencies if we're stitching tiles
if (fStitchTiles) {
- builder->fsCodeAppendf("\t\tif(%s.x >= %s.y) { %s.x -= %s.x; }",
- noiseXY, stitchData, noiseXY, stitchData);
- builder->fsCodeAppendf("\t\tif(%s.x >= (%s.y - 1.0)) { %s.x -= (%s.x - 1.0); }",
- noiseXY, stitchData, noiseXY, stitchData);
- builder->fsCodeAppendf("\t\tif(%s.y >= %s.w) { %s.y -= %s.z; }",
- noiseXY, stitchData, noiseXY, stitchData);
- builder->fsCodeAppendf("\t\tif(%s.y >= (%s.w - 1.0)) { %s.y -= (%s.z - 1.0); }",
- noiseXY, stitchData, noiseXY, stitchData);
+ noise_code.appendf("\n\tif(%s.x >= %s.y) { %s.x -= %s.x; }",
+ noiseXY, stitchData, noiseXY, stitchData);
+ noise_code.appendf("\n\tif(%s.x >= (%s.y - 1.0)) { %s.x -= (%s.x - 1.0); }",
+ noiseXY, stitchData, noiseXY, stitchData);
+ noise_code.appendf("\n\tif(%s.y >= %s.w) { %s.y -= %s.z; }",
+ noiseXY, stitchData, noiseXY, stitchData);
+ noise_code.appendf("\n\tif(%s.y >= (%s.w - 1.0)) { %s.y -= (%s.z - 1.0); }",
+ noiseXY, stitchData, noiseXY, stitchData);
}
// Get texture coordinates and normalize
- builder->fsCodeAppendf("\t\t%s.xy = fract(floor(mod(%s.xy, 256.0)) / vec2(256.0));",
- noiseXY, noiseXY);
+ noise_code.appendf("\n\t%s.xy = fract(floor(mod(%s.xy, 256.0)) / vec2(256.0));\n",
+ noiseXY, noiseXY);
// Get permutation for x
{
SkString xCoords("");
xCoords.appendf("vec2(%s.x, 0.5)", noiseXY);
- builder->fsCodeAppendf("\t\tvec2 %s;\t\t%s.x = ", latticeIdx, latticeIdx);
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[0], xCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppend(".r;\n");
+ noise_code.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx);
+ builder->appendTextureLookup(&noise_code, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
+ noise_code.append(".r;");
}
// Get permutation for x + 1
@@ -1067,104 +1061,145 @@
SkString xCoords("");
xCoords.appendf("vec2(fract(%s.x + %s), 0.5)", noiseXY, inc8bit);
- builder->fsCodeAppendf("\t\t%s.y = ", latticeIdx);
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[0], xCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppend(".r;\n");
+ noise_code.appendf("\n\t%s.y = ", latticeIdx);
+ builder->appendTextureLookup(&noise_code, samplers[0], xCoords.c_str(), kVec2f_GrSLType);
+ noise_code.append(".r;");
}
// Get (x,y) coordinates with the permutated x
- builder->fsCodeAppendf("\t\t%s = fract(%s + %s.yy);", latticeIdx, latticeIdx, noiseXY);
+ noise_code.appendf("\n\t%s = fract(%s + %s.yy);", latticeIdx, latticeIdx, noiseXY);
- builder->fsCodeAppendf("\t\tvec2 %s = %s.zw;", fractVal, noiseXY);
+ noise_code.appendf("\n\tvec2 %s = %s.zw;", fractVal, noiseXY);
- builder->fsCodeAppendf("\t\tvec2 %s;", uv);
+ noise_code.appendf("\n\n\tvec2 %s;", uv);
// Compute u, at offset (0,0)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(%s.x, %s[channel])", latticeIdx, chanCoords);
- builder->fsCodeAppendf("vec4 %s = ", lattice);
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[1], latticeCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppendf(".bgra;\n\t\t%s.x = ", uv);
- builder->fsCodeAppendf(dotLattice, lattice, lattice, inc8bit, fractVal);
+ latticeCoords.appendf("vec2(%s.x, %s)", latticeIdx, chanCoord);
+ noise_code.appendf("\n\tvec4 %s = ", lattice);
+ builder->appendTextureLookup(&noise_code, samplers[1], latticeCoords.c_str(),
+ kVec2f_GrSLType);
+ noise_code.appendf(".bgra;\n\t%s.x = ", uv);
+ noise_code.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
}
- builder->fsCodeAppendf("\t\t%s.x -= 1.0;", fractVal);
+ noise_code.appendf("\n\t%s.x -= 1.0;", fractVal);
// Compute v, at offset (-1,0)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(%s.y, %s[channel])", latticeIdx, chanCoords);
- builder->fsCodeAppend("lattice = ");
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[1], latticeCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppendf(".bgra;\n\t\t%s.y = ", uv);
- builder->fsCodeAppendf(dotLattice, lattice, lattice, inc8bit, fractVal);
+ latticeCoords.appendf("vec2(%s.y, %s)", latticeIdx, chanCoord);
+ noise_code.append("lattice = ");
+ builder->appendTextureLookup(&noise_code, samplers[1], latticeCoords.c_str(),
+ kVec2f_GrSLType);
+ noise_code.appendf(".bgra;\n\t%s.y = ", uv);
+ noise_code.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
}
// Compute 'a' as a linear interpolation of 'u' and 'v'
- builder->fsCodeAppendf("\t\tvec2 %s;", ab);
- builder->fsCodeAppendf("\t\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
+ noise_code.appendf("\n\tvec2 %s;", ab);
+ noise_code.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
- builder->fsCodeAppendf("\t\t%s.y -= 1.0;", fractVal);
+ noise_code.appendf("\n\t%s.y -= 1.0;", fractVal);
// Compute v, at offset (-1,-1)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(fract(%s.y + %s), %s[channel])",
- latticeIdx, inc8bit, chanCoords);
- builder->fsCodeAppend("lattice = ");
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[1], latticeCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppendf(".bgra;\n\t\t%s.y = ", uv);
- builder->fsCodeAppendf(dotLattice, lattice, lattice, inc8bit, fractVal);
+ latticeCoords.appendf("vec2(fract(%s.y + %s), %s)", latticeIdx, inc8bit, chanCoord);
+ noise_code.append("lattice = ");
+ builder->appendTextureLookup(&noise_code, samplers[1], latticeCoords.c_str(),
+ kVec2f_GrSLType);
+ noise_code.appendf(".bgra;\n\t%s.y = ", uv);
+ noise_code.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
}
- builder->fsCodeAppendf("\t\t%s.x += 1.0;", fractVal);
+ noise_code.appendf("\n\t%s.x += 1.0;", fractVal);
// Compute u, at offset (0,-1)
{
SkString latticeCoords("");
- latticeCoords.appendf("vec2(fract(%s.x + %s), %s[channel])",
- latticeIdx, inc8bit, chanCoords);
- builder->fsCodeAppend("lattice = ");
- builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
- samplers[1], latticeCoords.c_str(), kVec2f_GrSLType);
- builder->fsCodeAppendf(".bgra;\n\t\t%s.x = ", uv);
- builder->fsCodeAppendf(dotLattice, lattice, lattice, inc8bit, fractVal);
+ latticeCoords.appendf("vec2(fract(%s.x + %s), %s)", latticeIdx, inc8bit, chanCoord);
+ noise_code.append("lattice = ");
+ builder->appendTextureLookup(&noise_code, samplers[1], latticeCoords.c_str(),
+ kVec2f_GrSLType);
+ noise_code.appendf(".bgra;\n\t%s.x = ", uv);
+ noise_code.appendf(dotLattice, lattice, lattice, inc8bit, fractVal);
}
// Compute 'b' as a linear interpolation of 'u' and 'v'
- builder->fsCodeAppendf("\t\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
+ noise_code.appendf("\n\t%s.y = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth);
// Compute the noise as a linear interpolation of 'a' and 'b'
- builder->fsCodeAppendf("\t\tfloat %s = mix(%s.x, %s.y, %s.y);", noise, ab, ab, noiseSmooth);
+ noise_code.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth);
- builder->fsCodeAppendf("\t\t%s[channel] += ", outputColor);
- builder->fsCodeAppendf((fType == SkPerlinNoiseShader::kFractalNoise_Type) ?
- "%s / %s;" : "abs(%s) / %s;", noise, ratio);
+ SkString noise_funcName;
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, kFloat_GrSLType, "perlinnoise",
bsalomon 2013/06/10 13:39:25 Would this be easier to read if the there was just
+ fStitchTiles ? SK_ARRAY_COUNT(perlinnoise_stitch_Args) :
+ SK_ARRAY_COUNT(perlinnoise_Args),
+ fStitchTiles ? perlinnoise_stitch_Args : perlinnoise_Args,
+ noise_code.c_str(), &noise_funcName);
- builder->fsCodeAppendf("\t\t%s *= vec2(2.0);", noiseVec);
- builder->fsCodeAppendf("\t\t%s *= 2.0;", ratio);
+ // There are rounding errors if the floor operation is not performed here
+ builder->fsCodeAppendf("\n\t\tvec2 %s = floor((%s * vec3(%s, 1.0)).xy) * %s;",
+ noiseVec, invMatrixUni, vCoords, baseFrequencyUni);
+ // Clear the color accumulator
+ builder->fsCodeAppendf("\n\t\t%s = vec4(0.0);", outputColor);
+
if (fStitchTiles) {
- builder->fsCodeAppendf("\t\t%s.xz *= vec2(2.0);", stitchData);
- builder->fsCodeAppendf("\t\t%s.yw = %s.xz + vec2(%s);", stitchData, stitchData, perlinNoise);
+ // Set up TurbulenceInitial stitch values.
+ builder->fsCodeAppendf("\n\t\tvec4 %s = %s;", stitchData, stitchDataUni);
}
- builder->fsCodeAppend("\t\t}"); // end of the for loop on octaves
- builder->fsCodeAppend("\t\t}"); // end of the for loop on channels
+ builder->fsCodeAppendf("\n\t\tfloat %s = 1.0;", ratio);
+ // Loop over all octaves
+ builder->fsCodeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves);
+
+ builder->fsCodeAppendf("\n\t\t\t%s += ", outputColor);
+ if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
+ builder->fsCodeAppend("abs(");
+ }
+ if (fStitchTiles) {
+ builder->fsCodeAppendf(
+ "vec4(\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s),"
+ "\n\t\t\t\t%s(%s, %s, %s),\n\t\t\t\t%s(%s, %s, %s))",
+ noise_funcName.c_str(), chanCoordR, noiseVec, stitchData,
+ noise_funcName.c_str(), chanCoordG, noiseVec, stitchData,
+ noise_funcName.c_str(), chanCoordB, noiseVec, stitchData,
+ noise_funcName.c_str(), chanCoordA, noiseVec, stitchData);
+ } else {
+ builder->fsCodeAppendf(
+ "vec4(\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s),"
+ "\n\t\t\t\t%s(%s, %s),\n\t\t\t\t%s(%s, %s))",
+ noise_funcName.c_str(), chanCoordR, noiseVec,
+ noise_funcName.c_str(), chanCoordG, noiseVec,
+ noise_funcName.c_str(), chanCoordB, noiseVec,
+ noise_funcName.c_str(), chanCoordA, noiseVec);
+ }
+ if (fType != SkPerlinNoiseShader::kFractalNoise_Type) {
+ builder->fsCodeAppendf(")"); // end of "abs("
+ }
+ builder->fsCodeAppendf(" * %s;", ratio);
+
+ builder->fsCodeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec);
+ builder->fsCodeAppendf("\n\t\t\t%s *= 0.5;", ratio);
+
+ if (fStitchTiles) {
+ builder->fsCodeAppendf("\n\t\t\t%s.xz *= vec2(2.0);", stitchData);
+ builder->fsCodeAppendf("\n\t\t\t%s.yw = %s.xz + vec2(%s);", stitchData, stitchData, perlinNoise);
+ }
+ builder->fsCodeAppend("\n\t\t}"); // end of the for loop on octaves
+
if (fType == SkPerlinNoiseShader::kFractalNoise_Type) {
// The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult) + 1) / 2
// by fractalNoise and (turbulenceFunctionResult) by turbulence.
- builder->fsCodeAppendf("\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
+ builder->fsCodeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor);
}
- builder->fsCodeAppendf("\t\t%s.a *= %s;", outputColor, alphaUni);
+ builder->fsCodeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni);
// Clamp values
- builder->fsCodeAppendf("\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
+ builder->fsCodeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor);
// Pre-multiply the result
- builder->fsCodeAppendf("\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
+ builder->fsCodeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n",
outputColor, outputColor, outputColor, outputColor);
}
@@ -1295,7 +1330,7 @@
#else
GrEffectRef* SkPerlinNoiseShader::asNewEffect(GrContext*, const SkPaint&) const {
-#if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_WIN)
+#if !defined(SK_BUILD_FOR_ANDROID)
SkDEBUGFAIL("Should not call in GPU-less build");
#endif
return NULL;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698