void GrGLBicubicEffect::emitCode(EmitArgs& args) { const GrTextureDomain& domain = args.fFp.cast<GrBicubicEffect>().domain(); fCoefficientsUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kMat44f_GrSLType, kDefault_GrSLPrecision, "Coefficients"); fImageIncrementUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); const char* imgInc = args.fBuilder->getUniformCStr(fImageIncrementUni); const char* coeff = args.fBuilder->getUniformCStr(fCoefficientsUni); SkString cubicBlendName; static const GrGLShaderVar gCubicBlendArgs[] = { GrGLShaderVar("coefficients", kMat44f_GrSLType), GrGLShaderVar("t", kFloat_GrSLType), GrGLShaderVar("c0", kVec4f_GrSLType), GrGLShaderVar("c1", kVec4f_GrSLType), GrGLShaderVar("c2", kVec4f_GrSLType), GrGLShaderVar("c3", kVec4f_GrSLType), }; GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0); fsBuilder->emitFunction(kVec4f_GrSLType, "cubicBlend", SK_ARRAY_COUNT(gCubicBlendArgs), gCubicBlendArgs, "\tvec4 ts = vec4(1.0, t, t * t, t * t * t);\n" "\tvec4 c = coefficients * ts;\n" "\treturn c.x * c0 + c.y * c1 + c.z * c2 + c.w * c3;\n", &cubicBlendName); fsBuilder->codeAppendf("\tvec2 coord = %s - %s * vec2(0.5);\n", coords2D.c_str(), imgInc); // We unnormalize the coord in order to determine our fractional offset (f) within the texel // We then snap coord to a texel center and renormalize. The snap prevents cases where the // starting coords are near a texel boundary and accumulations of imgInc would cause us to skip/ // double hit a texel. fsBuilder->codeAppendf("\tcoord /= %s;\n", imgInc); fsBuilder->codeAppend("\tvec2 f = fract(coord);\n"); fsBuilder->codeAppendf("\tcoord = (coord - f + vec2(0.5)) * %s;\n", imgInc); fsBuilder->codeAppend("\tvec4 rowColors[4];\n"); for (int y = 0; y < 4; ++y) { for (int x = 0; x < 4; ++x) { SkString coord; coord.printf("coord + %s * vec2(%d, %d)", imgInc, x - 1, y - 1); SkString sampleVar; sampleVar.printf("rowColors[%d]", x); fDomain.sampleTexture(fsBuilder, domain, sampleVar.c_str(), coord, args.fSamplers[0]); } fsBuilder->codeAppendf("\tvec4 s%d = %s(%s, f.x, rowColors[0], rowColors[1], rowColors[2], rowColors[3]);\n", y, cubicBlendName.c_str(), coeff); } SkString bicubicColor; bicubicColor.printf("%s(%s, f.y, s0, s1, s2, s3)", cubicBlendName.c_str(), coeff); fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,(GrGLSLExpr4(bicubicColor.c_str()) * GrGLSLExpr4(args.fInputColor)).c_str()); }
void GrGLMagnifierEffect::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { fOffsetVar = builder->addUniform( GrGLProgramBuilder::kFragment_Visibility | GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Offset"); fInvZoomVar = builder->addUniform( GrGLProgramBuilder::kFragment_Visibility | GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "InvZoom"); fInvInsetVar = builder->addUniform( GrGLProgramBuilder::kFragment_Visibility | GrGLProgramBuilder::kVertex_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "InvInset"); fBoundsVar = builder->addUniform( GrGLProgramBuilder::kFragment_Visibility | GrGLProgramBuilder::kVertex_Visibility, kVec4f_GrSLType, kDefault_GrSLPrecision, "Bounds"); GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); fsBuilder->codeAppendf("\t\tvec2 zoom_coord = %s + %s * %s;\n", builder->getUniformCStr(fOffsetVar), coords2D.c_str(), builder->getUniformCStr(fInvZoomVar)); const char* bounds = builder->getUniformCStr(fBoundsVar); fsBuilder->codeAppendf("\t\tvec2 delta = (coord - %s.xy) * %s.zw;\n", bounds, bounds); fsBuilder->codeAppendf("\t\tdelta = min(delta, vec2(1.0, 1.0) - delta);\n"); fsBuilder->codeAppendf("\t\tdelta = delta * %s;\n", builder->getUniformCStr(fInvInsetVar)); fsBuilder->codeAppend("\t\tfloat weight = 0.0;\n"); fsBuilder->codeAppend("\t\tif (delta.s < 2.0 && delta.t < 2.0) {\n"); fsBuilder->codeAppend("\t\t\tdelta = vec2(2.0, 2.0) - delta;\n"); fsBuilder->codeAppend("\t\t\tfloat dist = length(delta);\n"); fsBuilder->codeAppend("\t\t\tdist = max(2.0 - dist, 0.0);\n"); fsBuilder->codeAppend("\t\t\tweight = min(dist * dist, 1.0);\n"); fsBuilder->codeAppend("\t\t} else {\n"); fsBuilder->codeAppend("\t\t\tvec2 delta_squared = delta * delta;\n"); fsBuilder->codeAppend("\t\t\tweight = min(min(delta_squared.x, delta_squared.y), 1.0);\n"); fsBuilder->codeAppend("\t\t}\n"); fsBuilder->codeAppend("\t\tvec2 mix_coord = mix(coord, zoom_coord, weight);\n"); fsBuilder->codeAppend("\t\tvec4 output_color = "); fsBuilder->appendTextureLookup(samplers[0], "mix_coord"); fsBuilder->codeAppend(";\n"); fsBuilder->codeAppendf("\t\t%s = output_color;", outputColor); SkString modulate; GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); fsBuilder->codeAppend(modulate.c_str()); }
void emitCode(EmitArgs& args) override { GrGLFragmentBuilder* fpb = args.fBuilder->getFragmentShaderBuilder(); fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(args.fCoords, 0).c_str()); fpb->codeAppend("vec2 r = mod(c, vec2(20.0));"); fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5," "0.5*cos((c.x + c.y) / 15.0) + 0.5," "(r.x + r.y) / 20.0," "distance(r, vec2(15.0)) / 20.0 + 0.2);"); fpb->codeAppendf("color.rgb *= color.a;" "%s = color * %s;", args.fOutputColor, GrGLSLExpr4(args.fInputColor).c_str()); }
void GrGLConvolutionEffect::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { fImageIncrementUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "ImageIncrement"); if (this->useBounds()) { fBoundsUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Bounds"); } fKernelUni = builder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "Kernel", this->width()); GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 0); fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", outputColor); int width = this->width(); const GrGLShaderVar& kernel = builder->getUniformVariable(fKernelUni); const char* imgInc = builder->getUniformCStr(fImageIncrementUni); fsBuilder->codeAppendf("\t\tvec2 coord = %s - %d.0 * %s;\n", coords2D.c_str(), fRadius, imgInc); // Manually unroll loop because some drivers don't; yields 20-30% speedup. for (int i = 0; i < width; i++) { SkString index; SkString kernelIndex; index.appendS32(i); kernel.appendArrayAccess(index.c_str(), &kernelIndex); fsBuilder->codeAppendf("\t\t%s += ", outputColor); fsBuilder->appendTextureLookup(samplers[0], "coord"); if (this->useBounds()) { const char* bounds = builder->getUniformCStr(fBoundsUni); const char* component = this->direction() == Gr1DKernelEffect::kY_Direction ? "y" : "x"; fsBuilder->codeAppendf(" * float(coord.%s >= %s.x && coord.%s <= %s.y)", component, bounds, component, bounds); } fsBuilder->codeAppendf(" * %s;\n", kernelIndex.c_str()); fsBuilder->codeAppendf("\t\tcoord += %s;\n", imgInc); } SkString modulate; GrGLSLMulVarBy4f(&modulate, outputColor, inputColor); fsBuilder->codeAppend(modulate.c_str()); }
void emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor& fp, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder(); fpb->codeAppendf("vec2 c = %s;", fpb->ensureFSCoords2D(coords, 0).c_str()); fpb->codeAppend("vec2 r = mod(c, vec2(20.0));"); fpb->codeAppend("vec4 color = vec4(0.5*sin(c.x / 15.0) + 0.5," "0.5*cos((c.x + c.y) / 15.0) + 0.5," "(r.x + r.y) / 20.0," "distance(r, vec2(15.0)) / 20.0 + 0.2);"); fpb->codeAppendf("color.rgb *= color.a;" "%s = color * %s;", outputColor, GrGLSLExpr4(inputColor).c_str()); }
void GrGLPerlinNoise::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor&, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { sk_ignore_unused_variable(inputColor); GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); SkString vCoords = fsBuilder->ensureFSCoords2D(coords, 0); fBaseFrequencyUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "baseFrequency"); const char* baseFrequencyUni = builder->getUniformCStr(fBaseFrequencyUni); fAlphaUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "alpha"); const char* alphaUni = builder->getUniformCStr(fAlphaUni); const char* stitchDataUni = NULL; if (fStitchTiles) { fStitchDataUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "stitchData"); stitchDataUni = builder->getUniformCStr(fStitchDataUni); } // 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* 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 // [-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);"; // Add noise function static const GrGLShaderVar gPerlinNoiseArgs[] = { GrGLShaderVar(chanCoord, kFloat_GrSLType), GrGLShaderVar(noiseVec, kVec2f_GrSLType) }; static const GrGLShaderVar gPerlinNoiseStitchArgs[] = { GrGLShaderVar(chanCoord, kFloat_GrSLType), GrGLShaderVar(noiseVec, kVec2f_GrSLType), GrGLShaderVar(stitchData, kVec2f_GrSLType) }; SkString noiseCode; 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 * %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; }", floorVal, stitchData, floorVal, stitchData); noiseCode.appendf("\n\tif(%s.y >= %s.y) { %s.y -= %s.y; }", 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 = 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)", floorVal); noiseCode.appendf("\n\tvec2 %s;\n\t%s.x = ", latticeIdx, latticeIdx); fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } // Get permutation for x + 1 { SkString xCoords(""); xCoords.appendf("vec2(%s.z, 0.5)", floorVal); noiseCode.appendf("\n\t%s.y = ", latticeIdx); fsBuilder->appendTextureLookup(&noiseCode, samplers[0], xCoords.c_str(), kVec2f_GrSLType); noiseCode.append(".r;"); } #if defined(SK_BUILD_FOR_ANDROID) // Android rounding for Tegra devices, like, for example: Xoom (Tegra 2), Nexus 7 (Tegra 3). // The issue is that colors aren't accurate enough on Tegra devices. For example, if an 8 bit // value of 124 (or 0.486275 here) is entered, we can get a texture value of 123.513725 // (or 0.484368 here). The following rounding operation prevents these precision issues from // affecting the result of the noise by making sure that we only have multiples of 1/255. // (Note that 1/255 is about 0.003921569, which is the value used here). noiseCode.appendf("\n\t%s = floor(%s * vec2(255.0) + vec2(0.5)) * vec2(0.003921569);", latticeIdx, latticeIdx); #endif // Get (x,y) coordinates with the permutated x 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)", bcoords, chanCoord); noiseCode.appendf("\n\tvec4 %s = ", lattice); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } noiseCode.appendf("\n\t%s.x -= 1.0;", fractVal); // Compute v, at offset (-1,0) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.y, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } // Compute 'a' as a linear interpolation of 'u' and 'v' noiseCode.appendf("\n\tvec2 %s;", ab); noiseCode.appendf("\n\t%s.x = mix(%s.x, %s.y, %s.x);", ab, uv, uv, noiseSmooth); noiseCode.appendf("\n\t%s.y -= 1.0;", fractVal); // Compute v, at offset (-1,-1) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.w, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.y = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } noiseCode.appendf("\n\t%s.x += 1.0;", fractVal); // Compute u, at offset (0,-1) { SkString latticeCoords(""); latticeCoords.appendf("vec2(%s.z, %s)", bcoords, chanCoord); noiseCode.append("\n\tlattice = "); fsBuilder->appendTextureLookup(&noiseCode, samplers[1], latticeCoords.c_str(), kVec2f_GrSLType); noiseCode.appendf(".bgra;\n\t%s.x = ", uv); noiseCode.appendf(dotLattice, lattice, lattice, inc8bit, fractVal); } // Compute 'b' as a linear interpolation of 'u' and 'v' noiseCode.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' noiseCode.appendf("\n\treturn mix(%s.x, %s.y, %s.y);\n", ab, ab, noiseSmooth); SkString noiseFuncName; if (fStitchTiles) { fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseStitchArgs), gPerlinNoiseStitchArgs, noiseCode.c_str(), &noiseFuncName); } else { fsBuilder->emitFunction(kFloat_GrSLType, "perlinnoise", SK_ARRAY_COUNT(gPerlinNoiseArgs), gPerlinNoiseArgs, noiseCode.c_str(), &noiseFuncName); } // There are rounding errors if the floor operation is not performed here fsBuilder->codeAppendf("\n\t\tvec2 %s = floor(%s.xy) * %s;", noiseVec, vCoords.c_str(), baseFrequencyUni); // Clear the color accumulator fsBuilder->codeAppendf("\n\t\t%s = vec4(0.0);", outputColor); if (fStitchTiles) { // Set up TurbulenceInitial stitch values. fsBuilder->codeAppendf("\n\t\tvec2 %s = %s;", stitchData, stitchDataUni); } fsBuilder->codeAppendf("\n\t\tfloat %s = 1.0;", ratio); // Loop over all octaves fsBuilder->codeAppendf("\n\t\tfor (int octave = 0; octave < %d; ++octave) {", fNumOctaves); fsBuilder->codeAppendf("\n\t\t\t%s += ", outputColor); if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { fsBuilder->codeAppend("abs("); } if (fStitchTiles) { fsBuilder->codeAppendf( "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))", noiseFuncName.c_str(), chanCoordR, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordG, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordB, noiseVec, stitchData, noiseFuncName.c_str(), chanCoordA, noiseVec, stitchData); } else { fsBuilder->codeAppendf( "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))", noiseFuncName.c_str(), chanCoordR, noiseVec, noiseFuncName.c_str(), chanCoordG, noiseVec, noiseFuncName.c_str(), chanCoordB, noiseVec, noiseFuncName.c_str(), chanCoordA, noiseVec); } if (fType != SkPerlinNoiseShader::kFractalNoise_Type) { fsBuilder->codeAppendf(")"); // end of "abs(" } fsBuilder->codeAppendf(" * %s;", ratio); fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", noiseVec); fsBuilder->codeAppendf("\n\t\t\t%s *= 0.5;", ratio); if (fStitchTiles) { fsBuilder->codeAppendf("\n\t\t\t%s *= vec2(2.0);", stitchData); } fsBuilder->codeAppend("\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. fsBuilder->codeAppendf("\n\t\t%s = %s * vec4(0.5) + vec4(0.5);", outputColor, outputColor); } fsBuilder->codeAppendf("\n\t\t%s.a *= %s;", outputColor, alphaUni); // Clamp values fsBuilder->codeAppendf("\n\t\t%s = clamp(%s, 0.0, 1.0);", outputColor, outputColor); // Pre-multiply the result fsBuilder->codeAppendf("\n\t\t%s = vec4(%s.rgb * %s.aaa, %s.a);\n", outputColor, outputColor, outputColor, outputColor); }
void GrGLDisplacementMapEffect::emitCode(GrGLFPBuilder* builder, const GrFragmentProcessor& fp, const char* outputColor, const char* inputColor, const TransformedCoordsArray& coords, const TextureSamplerArray& samplers) { const GrTextureDomain& domain = fp.cast<GrDisplacementMapEffect>().domain(); sk_ignore_unused_variable(inputColor); fScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale"); const char* scaleUni = builder->getUniformCStr(fScaleUni); const char* dColor = "dColor"; const char* cCoords = "cCoords"; const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use // a number smaller than that to approximate 0, but // leave room for 32-bit float GPU rounding errors. GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder(); fsBuilder->codeAppendf("\t\tvec4 %s = ", dColor); fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType()); fsBuilder->codeAppend(";\n"); // Unpremultiply the displacement fsBuilder->codeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", dColor, dColor, nearZero, dColor, dColor); SkString coords2D = fsBuilder->ensureFSCoords2D(coords, 1); fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.", cCoords, coords2D.c_str(), scaleUni, dColor); switch (fXChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: fsBuilder->codeAppend("r"); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: fsBuilder->codeAppend("g"); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: fsBuilder->codeAppend("b"); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: fsBuilder->codeAppend("a"); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: SkDEBUGFAIL("Unknown X channel selector"); } switch (fYChannelSelector) { case SkDisplacementMapEffect::kR_ChannelSelectorType: fsBuilder->codeAppend("r"); break; case SkDisplacementMapEffect::kG_ChannelSelectorType: fsBuilder->codeAppend("g"); break; case SkDisplacementMapEffect::kB_ChannelSelectorType: fsBuilder->codeAppend("b"); break; case SkDisplacementMapEffect::kA_ChannelSelectorType: fsBuilder->codeAppend("a"); break; case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: default: SkDEBUGFAIL("Unknown Y channel selector"); } fsBuilder->codeAppend("-vec2(0.5));\t\t"); fGLDomain.sampleTexture(fsBuilder, domain, outputColor, SkString(cCoords), samplers[1]); fsBuilder->codeAppend(";\n"); }
void GrGLMorphologyEffect::emitCode(EmitArgs& args) { fPixelSizeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kFloat_GrSLType, kDefault_GrSLPrecision, "PixelSize"); const char* pixelSizeInc = args.fBuilder->getUniformCStr(fPixelSizeUni); fRangeUni = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility, kVec2f_GrSLType, kDefault_GrSLPrecision, "Range"); const char* range = args.fBuilder->getUniformCStr(fRangeUni); GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder(); SkString coords2D = fsBuilder->ensureFSCoords2D(args.fCoords, 0); const char* func; switch (fType) { case GrMorphologyEffect::kErode_MorphologyType: fsBuilder->codeAppendf("\t\t%s = vec4(1, 1, 1, 1);\n", args.fOutputColor); func = "min"; break; case GrMorphologyEffect::kDilate_MorphologyType: fsBuilder->codeAppendf("\t\t%s = vec4(0, 0, 0, 0);\n", args.fOutputColor); func = "max"; break; default: SkFAIL("Unexpected type"); func = ""; // suppress warning break; } const char* dir; switch (fDirection) { case Gr1DKernelEffect::kX_Direction: dir = "x"; break; case Gr1DKernelEffect::kY_Direction: dir = "y"; break; default: SkFAIL("Unknown filter direction."); dir = ""; // suppress warning } // vec2 coord = coord2D; fsBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); // coord.x -= radius * pixelSize; fsBuilder->codeAppendf("\t\tcoord.%s -= %d.0 * %s; \n", dir, fRadius, pixelSizeInc); if (fUseRange) { // highBound = min(highBound, coord.x + (width-1) * pixelSize); fsBuilder->codeAppendf("\t\tfloat highBound = min(%s.y, coord.%s + %f * %s);", range, dir, float(width() - 1), pixelSizeInc); // coord.x = max(lowBound, coord.x); fsBuilder->codeAppendf("\t\tcoord.%s = max(%s.x, coord.%s);", dir, range, dir); } fsBuilder->codeAppendf("\t\tfor (int i = 0; i < %d; i++) {\n", width()); fsBuilder->codeAppendf("\t\t\t%s = %s(%s, ", args.fOutputColor, func, args.fOutputColor); fsBuilder->appendTextureLookup(args.fSamplers[0], "coord"); fsBuilder->codeAppend(");\n"); // coord.x += pixelSize; fsBuilder->codeAppendf("\t\t\tcoord.%s += %s;\n", dir, pixelSizeInc); if (fUseRange) { // coord.x = min(highBound, coord.x); fsBuilder->codeAppendf("\t\t\tcoord.%s = min(highBound, coord.%s);", dir, dir); } fsBuilder->codeAppend("\t\t}\n"); SkString modulate; GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor); fsBuilder->codeAppend(modulate.c_str()); }