本文整理汇总了C++中GrGLFragmentBuilder类的典型用法代码示例。如果您正苦于以下问题:C++ GrGLFragmentBuilder类的具体用法?C++ GrGLFragmentBuilder怎么用?C++ GrGLFragmentBuilder使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了GrGLFragmentBuilder类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: v
void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>();
const CubicBatchTracker& local = args.fBT.cast<CubicBatchTracker>();
// emit attributes
vsBuilder->emitAttributes(gp);
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName);
// Setup pass through color
this->setupColorPassThrough(args.fPB, local.fInputColorType, args.fOutputColor, NULL,
&fColorUniform);
// Setup position
this->setupPosition(args.fPB, gpArgs, gp.inPosition()->fName, gp.viewMatrix());
// emit transforms with position
this->emitTransforms(args.fPB, gpArgs->fPositionVar, gp.inPosition()->fName, args.fTransformsIn,
args.fTransformsOut);
GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
GrGLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar dklmdx("dklmdx", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar dklmdy("dklmdy", kVec3f_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar dfdx("dfdx", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar dfdy("dfdy", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar gF("gF", kVec2f_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar gFM("gFM", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
GrGLShaderVar func("func", kFloat_GrSLType, 0, kHigh_GrSLPrecision);
fsBuilder->declAppend(edgeAlpha);
fsBuilder->declAppend(dklmdx);
fsBuilder->declAppend(dklmdy);
fsBuilder->declAppend(dfdx);
fsBuilder->declAppend(dfdy);
fsBuilder->declAppend(gF);
fsBuilder->declAppend(gFM);
fsBuilder->declAppend(func);
switch (fEdgeType) {
case kHairlineAA_GrProcessorEdgeType: {
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
fsBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
fsBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
fsBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
fsBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
fsBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
fsBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", gFM.c_str(), gF.c_str(), gF.c_str());
fsBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
fsBuilder->codeAppendf("%s = abs(%s);", func.c_str(), func.c_str());
fsBuilder->codeAppendf("%s = %s / %s;",
edgeAlpha.c_str(), func.c_str(), gFM.c_str());
fsBuilder->codeAppendf("%s = max(1.0 - %s, 0.0);",
edgeAlpha.c_str(), edgeAlpha.c_str());
// Add line below for smooth cubic ramp
// fsBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
// edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
// edgeAlpha.c_str());
break;
}
case kFillAA_GrProcessorEdgeType: {
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
fsBuilder->codeAppendf("%s = dFdx(%s.xyz);", dklmdx.c_str(), v.fsIn());
fsBuilder->codeAppendf("%s = dFdy(%s.xyz);", dklmdy.c_str(), v.fsIn());
fsBuilder->codeAppendf("%s ="
"3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
dfdx.c_str(), v.fsIn(), v.fsIn(), dklmdx.c_str(), v.fsIn(),
dklmdx.c_str(), v.fsIn(), dklmdx.c_str());
fsBuilder->codeAppendf("%s = 3.0 * %s.x * %s.x * %s.x - %s.y * %s.z - %s.z * %s.y;",
dfdy.c_str(), v.fsIn(), v.fsIn(), dklmdy.c_str(), v.fsIn(),
dklmdy.c_str(), v.fsIn(), dklmdy.c_str());
fsBuilder->codeAppendf("%s = vec2(%s, %s);", gF.c_str(), dfdx.c_str(), dfdy.c_str());
fsBuilder->codeAppendf("%s = sqrt(dot(%s, %s));", gFM.c_str(), gF.c_str(), gF.c_str());
fsBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
func.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
fsBuilder->codeAppendf("%s = %s / %s;",
edgeAlpha.c_str(), func.c_str(), gFM.c_str());
fsBuilder->codeAppendf("%s = clamp(1.0 - %s, 0.0, 1.0);",
edgeAlpha.c_str(), edgeAlpha.c_str());
// Add line below for smooth cubic ramp
// fsBuilder->codeAppendf("%s = %s * %s * (3.0 - 2.0 * %s);",
// edgeAlpha.c_str(), edgeAlpha.c_str(), edgeAlpha.c_str(),
// edgeAlpha.c_str());
break;
}
case kFillBW_GrProcessorEdgeType: {
fsBuilder->codeAppendf("%s = %s.x * %s.x * %s.x - %s.y * %s.z;",
edgeAlpha.c_str(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn(), v.fsIn());
fsBuilder->codeAppendf("%s = float(%s < 0.0);", edgeAlpha.c_str(), edgeAlpha.c_str());
//.........这里部分代码省略.........
示例2: emitCode
void GLEllipticalRRectEffect::emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor& effect,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray&,
const TextureSamplerArray& samplers) {
const EllipticalRRectEffect& erre = effect.cast<EllipticalRRectEffect>();
const char *rectName;
// The inner rect is the rrect bounds inset by the x/y radii
fInnerRectUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"innerRect",
&rectName);
GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
const char* fragmentPos = fsBuilder->fragmentPosition();
// At each quarter-ellipse corner we compute a vector that is the offset of the fragment pos
// to the ellipse center. The vector is pinned in x and y to be in the quarter-plane relevant
// to that corner. This means that points near the interior near the rrect top edge will have
// a vector that points straight up for both the TL left and TR corners. Computing an
// alpha from this vector at either the TR or TL corner will give the correct result. Similarly,
// fragments near the other three edges will get the correct AA. Fragments in the interior of
// the rrect will have a (0,0) vector at all four corners. So long as the radii > 0.5 they will
// correctly produce an alpha value of 1 at all four corners. We take the min of all the alphas.
// The code below is a simplified version of the above that performs maxs on the vector
// components before computing distances and alpha values so that only one distance computation
// need be computed to determine the min alpha.
fsBuilder->codeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos);
fsBuilder->codeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rectName);
switch (erre.getRRect().getType()) {
case SkRRect::kSimple_Type: {
const char *invRadiiXYSqdName;
fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec2f_GrSLType, kDefault_GrSLPrecision,
"invRadiiXY",
&invRadiiXYSqdName);
fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
// Z is the x/y offsets divided by squared radii.
fsBuilder->codeAppendf("\t\tvec2 Z = dxy * %s;\n", invRadiiXYSqdName);
break;
}
case SkRRect::kNinePatch_Type: {
const char *invRadiiLTRBSqdName;
fInvRadiiSqdUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"invRadiiLTRB",
&invRadiiLTRBSqdName);
fsBuilder->codeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n");
// Z is the x/y offsets divided by squared radii. We only care about the (at most) one
// corner where both the x and y offsets are positive, hence the maxes. (The inverse
// squared radii will always be positive.)
fsBuilder->codeAppendf("\t\tvec2 Z = max(max(dxy0 * %s.xy, dxy1 * %s.zw), 0.0);\n",
invRadiiLTRBSqdName, invRadiiLTRBSqdName);
break;
}
default:
SkFAIL("RRect should always be simple or nine-patch.");
}
// implicit is the evaluation of (x/a)^2 + (y/b)^2 - 1.
fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, dxy) - 1.0;\n");
// grad_dot is the squared length of the gradient of the implicit.
fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
// avoid calling inversesqrt on zero.
fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
if (kFillAA_GrProcessorEdgeType == erre.getEdgeType()) {
fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
} else {
fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
}
fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
(GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
}
示例3: emitCode
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());
}
示例4: emitCode
virtual void emitCode(EmitArgs& args) override {
// Using highp for GLES here in order to avoid some precision issues on specific GPUs.
GrGLShaderVar tmpVar("tmpColor", kVec4f_GrSLType, 0, kHigh_GrSLPrecision);
SkString tmpDecl;
tmpVar.appendDecl(args.fBuilder->ctxInfo(), &tmpDecl);
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("%s;", tmpDecl.c_str());
fsBuilder->codeAppendf("%s = ", tmpVar.c_str());
fsBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
args.fCoords[0].getType());
fsBuilder->codeAppend(";");
if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
SkASSERT(fSwapRedAndBlue);
fsBuilder->codeAppendf("%s = %s.bgra;", args.fOutputColor, tmpVar.c_str());
} else {
const char* swiz = fSwapRedAndBlue ? "bgr" : "rgb";
switch (fPMConversion) {
case GrConfigConversionEffect::kMulByAlpha_RoundUp_PMConversion:
fsBuilder->codeAppendf(
"%s = vec4(ceil(%s.%s * %s.a * 255.0) / 255.0, %s.a);",
tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
break;
case GrConfigConversionEffect::kMulByAlpha_RoundDown_PMConversion:
// Add a compensation(0.001) here to avoid the side effect of the floor operation.
// In Intel GPUs, the integer value converted from floor(%s.r * 255.0) / 255.0
// is less than the integer value converted from %s.r by 1 when the %s.r is
// converted from the integer value 2^n, such as 1, 2, 4, 8, etc.
fsBuilder->codeAppendf(
"%s = vec4(floor(%s.%s * %s.a * 255.0 + 0.001) / 255.0, %s.a);",
tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
break;
case GrConfigConversionEffect::kDivByAlpha_RoundUp_PMConversion:
fsBuilder->codeAppendf(
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(ceil(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
break;
case GrConfigConversionEffect::kDivByAlpha_RoundDown_PMConversion:
fsBuilder->codeAppendf(
"%s = %s.a <= 0.0 ? vec4(0,0,0,0) : vec4(floor(%s.%s / %s.a * 255.0) / 255.0, %s.a);",
tmpVar.c_str(), tmpVar.c_str(), tmpVar.c_str(), swiz, tmpVar.c_str(), tmpVar.c_str());
break;
default:
SkFAIL("Unknown conversion op.");
break;
}
fsBuilder->codeAppendf("%s = %s;", args.fOutputColor, tmpVar.c_str());
}
SkString modulate;
GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
fsBuilder->codeAppend(modulate.c_str());
}
示例5: emitCode
virtual void emitCode(EmitArgs& args) override {
// pass through
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
fsBuilder->codeAppendf("%s = %s;\n", args.fOutputColor, args.fInputColor);
}
示例6: emitCode
void GLEllipseEffect::emitCode(EmitArgs& args) {
const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
const char *ellipseName;
// The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
// The last two terms can underflow on mediump, so we use highp.
fEllipseUniform = args.fBuilder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kHigh_GrSLPrecision,
"ellipse",
&ellipseName);
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
const char* fragmentPos = fsBuilder->fragmentPosition();
// d is the offset to the ellipse center
fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
// grad_dot is the squared length of the gradient of the implicit.
fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
// avoid calling inversesqrt on zero.
fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
switch (ee.getEdgeType()) {
case kFillAA_GrProcessorEdgeType:
fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
break;
case kInverseFillAA_GrProcessorEdgeType:
fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
break;
case kFillBW_GrProcessorEdgeType:
fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
break;
case kInverseFillBW_GrProcessorEdgeType:
fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
break;
case kHairlineAA_GrProcessorEdgeType:
SkFAIL("Hairline not expected here.");
}
fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
(GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
}
示例7: sk_ignore_unused_variable
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
//.........这里部分代码省略.........
示例8: onEmitCode
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override{
const GrDistanceFieldA8TextGeoProc& dfTexEffect =
args.fGP.cast<GrDistanceFieldA8TextGeoProc>();
GrGLGPBuilder* pb = args.fPB;
GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(dfTexEffect);
#ifdef SK_GAMMA_APPLY_TO_A8
// adjust based on gamma
const char* distanceAdjustUniName = NULL;
// width, height, 1/(3*width)
fDistanceAdjustUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kDefault_GrSLPrecision,
"DistanceAdjust", &distanceAdjustUniName);
#endif
// Setup pass through color
if (!dfTexEffect.colorIgnored()) {
if (dfTexEffect.hasVertexColor()) {
pb->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
} else {
this->setupUniformColor(pb, args.fOutputColor, &fColorUniform);
}
}
// Setup position
this->setupPosition(pb, gpArgs, dfTexEffect.inPosition()->fName, dfTexEffect.viewMatrix(),
&fViewMatrixUniform);
// emit transforms
this->emitTransforms(args.fPB, gpArgs->fPositionVar, dfTexEffect.inPosition()->fName,
args.fTransformsIn, args.fTransformsOut);
// add varyings
GrGLVertToFrag recipScale(kFloat_GrSLType);
GrGLVertToFrag st(kVec2f_GrSLType);
bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
args.fPB->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
// compute numbers to be hardcoded to convert texture coordinates from int to float
SkASSERT(dfTexEffect.numTextures() == 1);
GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture();
SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
SkScalar recipWidth = 1.0f / atlas->width();
SkScalar recipHeight = 1.0f / atlas->height();
GrGLVertToFrag uv(kVec2f_GrSLType);
args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(),
GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight,
dfTexEffect.inTextureCoords()->fName);
// Use highp to work around aliasing issues
fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision,
pb->ctxInfo().standard()));
fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
fsBuilder->codeAppend("\tfloat texColor = ");
fsBuilder->appendTextureLookup(args.fSamplers[0],
"uv",
kVec2f_GrSLType);
fsBuilder->codeAppend(".r;\n");
fsBuilder->codeAppend("\tfloat distance = "
SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
#ifdef SK_GAMMA_APPLY_TO_A8
// adjust width based on gamma
fsBuilder->codeAppendf("distance -= %s;", distanceAdjustUniName);
#endif
fsBuilder->codeAppend("float afwidth;");
if (isSimilarity) {
// For uniform scale, we adjust for the effect of the transformation on the distance
// by using the length of the gradient of the texture coordinates. We use st coordinates
// to ensure we're mapping 1:1 from texel space to pixel space.
// this gives us a smooth step across approximately one fragment
// we use y to work around a Mali400 bug in the x direction
fsBuilder->codeAppendf("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdy(%s.y));",
st.fsIn());
} else {
// For general transforms, to determine the amount of correction we multiply a unit
// vector pointing along the SDF gradient direction by the Jacobian of the st coords
// (which is the inverse transform for this fragment) and take the length of the result.
fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(distance));");
// the length of the gradient may be 0, so we need to check for this
// this also compensates for the Adreno, which likes to drop tiles on division by 0
fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad);");
fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
fsBuilder->codeAppend("} else {");
fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);");
fsBuilder->codeAppend("}");
//.........这里部分代码省略.........
示例9: emitCode
void GrGLConvexPolyEffect::emitCode(EmitArgs& args) {
const GrConvexPolyEffect& cpe = args.fFp.cast<GrConvexPolyEffect>();
const char *edgeArrayName;
fEdgeUniform = args.fBuilder->addUniformArray(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType,
kDefault_GrSLPrecision,
"edges",
cpe.getEdgeCount(),
&edgeArrayName);
GrGLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
fsBuilder->codeAppend("\t\tfloat alpha = 1.0;\n");
fsBuilder->codeAppend("\t\tfloat edge;\n");
const char* fragmentPos = fsBuilder->fragmentPosition();
for (int i = 0; i < cpe.getEdgeCount(); ++i) {
fsBuilder->codeAppendf("\t\tedge = dot(%s[%d], vec3(%s.x, %s.y, 1));\n",
edgeArrayName, i, fragmentPos, fragmentPos);
if (GrProcessorEdgeTypeIsAA(cpe.getEdgeType())) {
fsBuilder->codeAppend("\t\tedge = clamp(edge, 0.0, 1.0);\n");
} else {
fsBuilder->codeAppend("\t\tedge = edge >= 0.5 ? 1.0 : 0.0;\n");
}
fsBuilder->codeAppend("\t\talpha *= edge;\n");
}
// Woe is me. See skbug.com/2149.
if (kTegra2_GrGLRenderer == args.fBuilder->ctxInfo().renderer()) {
fsBuilder->codeAppend("\t\tif (-1.0 == alpha) {\n\t\t\tdiscard;\n\t\t}\n");
}
if (GrProcessorEdgeTypeIsInverseFill(cpe.getEdgeType())) {
fsBuilder->codeAppend("\talpha = 1.0 - alpha;\n");
}
fsBuilder->codeAppendf("\t%s = %s;\n", args.fOutputColor,
(GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
}
示例10: emitCode
void emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor& fp,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) override {
GrGLFragmentBuilder* fpb = builder->getFragmentShaderBuilder();
// add uniforms
const char* lightDirUniName = NULL;
fLightDirUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec3f_GrSLType, kDefault_GrSLPrecision,
"LightDir", &lightDirUniName);
const char* lightColorUniName = NULL;
fLightColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"LightColor", &lightColorUniName);
const char* ambientColorUniName = NULL;
fAmbientColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kVec4f_GrSLType, kDefault_GrSLPrecision,
"AmbientColor", &ambientColorUniName);
fpb->codeAppend("vec4 diffuseColor = ");
fpb->appendTextureLookupAndModulate(inputColor, samplers[0],
coords[0].c_str(), coords[0].getType());
fpb->codeAppend(";");
fpb->codeAppend("vec4 normalColor = ");
fpb->appendTextureLookup(samplers[1], coords[0].c_str(), coords[0].getType());
fpb->codeAppend(";");
fpb->codeAppend("vec3 normal = normalize(2.0*(normalColor.rgb - vec3(0.5)));");
fpb->codeAppendf("vec3 lightDir = normalize(%s);", lightDirUniName);
fpb->codeAppend("float NdotL = dot(normal, lightDir);");
// diffuse light
fpb->codeAppendf("vec3 result = %s.rgb*diffuseColor.rgb*NdotL;", lightColorUniName);
// ambient light
fpb->codeAppendf("result += %s.rgb;", ambientColorUniName);
fpb->codeAppendf("%s = vec4(result.rgb, diffuseColor.a);", outputColor);
}
示例11: sk_ignore_unused_variable
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");
}
示例12: emitCode
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());
}
示例13: emitChild
void GrGLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
const char* outputColor, EmitArgs& args) {
GrGLFragmentBuilder* fb = args.fBuilder->getFragmentShaderBuilder();
fb->onBeforeChildProcEmitCode(); // call first so mangleString is updated
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
/*
* We now want to find the subset of coords and samplers that belong to the child and its
* descendants and put that into childCoords and childSamplers. To do so, we'll do a forwards
* linear search.
*
* Explanation:
* Each GrFragmentProcessor has a copy of all the transforms and textures of itself and
* all procs in its subtree. For example, suppose we have frag proc A, who has two children B
* and D. B has a child C, and D has two children E and F. Each frag proc's transforms array
* contains its own transforms, followed by the transforms of all its descendants (i.e. preorder
* traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively.
*
* (A)
* [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
* / \
* / \
* (B) (D)
* [b1,b2,c1] [d1,e1,e2,e3,f1,f2]
* / / \
* / / \
* (C) (E) (F)
* [c1] [e1,e2,e3] [f1,f2]
*
* So if we're inside proc A's emitCode, and A is about to call emitCode on proc D, we want the
* EmitArgs that's passed onto D to only contain its and its descendants' coords. The
* EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want
* to extract the subset [d1,e1,e2,e3,f1,f2] to pass on to D. We can do this with a linear
* search since we know that A has 1 transform (using A.numTransformsExclChildren()), and B's
* subtree has 3 transforms (using B.numTransforms()), so we know the start of D's transforms is
* 4 after the start of A's transforms.
* Textures work the same way as transforms.
*/
int firstCoordAt = args.fFp.numTransformsExclChildren();
int firstSamplerAt = args.fFp.numTexturesExclChildren();
for (int i = 0; i < childIndex; ++i) {
firstCoordAt += args.fFp.childProcessor(i).numTransforms();
firstSamplerAt += args.fFp.childProcessor(i).numTextures();
}
TransformedCoordsArray childCoords;
TextureSamplerArray childSamplers;
if (childProc.numTransforms() > 0) {
childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]);
}
if (childProc.numTextures() > 0) {
childSamplers.push_back_n(childProc.numTextures(), &args.fSamplers[firstSamplerAt]);
}
// emit the code for the child in its own scope
fb->codeAppend("{\n");
fb->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
fb->getMangleString().c_str(), childProc.name());
EmitArgs childArgs(args.fBuilder,
childProc,
outputColor,
inputColor,
childCoords,
childSamplers);
this->childProcessor(childIndex)->emitCode(childArgs);
fb->codeAppend("}\n");
fb->onAfterChildProcEmitCode();
}
示例14: onEmitCode
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>();
GrGLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
// emit attributes
vsBuilder->emitAttributes(qe);
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("QuadEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName);
const BatchTracker& local = args.fBT.cast<BatchTracker>();
// Setup pass through color
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
&fColorUniform);
// Setup position
this->setupPosition(pb, gpArgs, qe.inPosition()->fName, qe.viewMatrix());
// emit transforms
this->emitTransforms(args.fPB, gpArgs->fPositionVar, qe.inPosition()->fName,
qe.localMatrix(), args.fTransformsIn, args.fTransformsOut);
GrGLFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
fsBuilder->codeAppendf("float edgeAlpha;");
// keep the derivative instructions outside the conditional
fsBuilder->codeAppendf("vec2 duvdx = dFdx(%s.xy);", v.fsIn());
fsBuilder->codeAppendf("vec2 duvdy = dFdy(%s.xy);", v.fsIn());
fsBuilder->codeAppendf("if (%s.z > 0.0 && %s.w > 0.0) {", v.fsIn(), v.fsIn());
// today we know z and w are in device space. We could use derivatives
fsBuilder->codeAppendf("edgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);", v.fsIn(),
v.fsIn());
fsBuilder->codeAppendf ("} else {");
fsBuilder->codeAppendf("vec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,"
" 2.0*%s.x*duvdy.x - duvdy.y);",
v.fsIn(), v.fsIn());
fsBuilder->codeAppendf("edgeAlpha = (%s.x*%s.x - %s.y);", v.fsIn(), v.fsIn(),
v.fsIn());
fsBuilder->codeAppendf("edgeAlpha = "
"clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);}");
fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
}
示例15: max
void GrColorCubeEffect::GLProcessor::emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor&,
const char* outputColor,
const char* inputColor,
const TransformedCoordsArray& coords,
const TextureSamplerArray& samplers) {
if (NULL == inputColor) {
inputColor = "vec4(1)";
}
fColorCubeSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kDefault_GrSLPrecision,
"Size");
const char* colorCubeSizeUni = builder->getUniformCStr(fColorCubeSizeUni);
fColorCubeInvSizeUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
kFloat_GrSLType, kDefault_GrSLPrecision,
"InvSize");
const char* colorCubeInvSizeUni = builder->getUniformCStr(fColorCubeInvSizeUni);
const char* nonZeroAlpha = "nonZeroAlpha";
const char* unPMColor = "unPMColor";
const char* cubeIdx = "cubeIdx";
const char* cCoords1 = "cCoords1";
const char* cCoords2 = "cCoords2";
// Note: if implemented using texture3D in OpenGL ES older than OpenGL ES 3.0,
// the shader might need "#extension GL_OES_texture_3D : enable".
GrGLFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
// Unpremultiply color
fsBuilder->codeAppendf("\tfloat %s = max(%s.a, 0.00001);\n", nonZeroAlpha, inputColor);
fsBuilder->codeAppendf("\tvec4 %s = vec4(%s.rgb / %s, %s);\n",
unPMColor, inputColor, nonZeroAlpha, nonZeroAlpha);
// Fit input color into the cube.
fsBuilder->codeAppendf(
"vec3 %s = vec3(%s.rg * vec2((%s - 1.0) * %s) + vec2(0.5 * %s), %s.b * (%s - 1.0));\n",
cubeIdx, unPMColor, colorCubeSizeUni, colorCubeInvSizeUni, colorCubeInvSizeUni,
unPMColor, colorCubeSizeUni);
// Compute y coord for for texture fetches.
fsBuilder->codeAppendf("vec2 %s = vec2(%s.r, (floor(%s.b) + %s.g) * %s);\n",
cCoords1, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);
fsBuilder->codeAppendf("vec2 %s = vec2(%s.r, (ceil(%s.b) + %s.g) * %s);\n",
cCoords2, cubeIdx, cubeIdx, cubeIdx, colorCubeInvSizeUni);
// Apply the cube.
fsBuilder->codeAppendf("%s = vec4(mix(", outputColor);
fsBuilder->appendTextureLookup(samplers[0], cCoords1);
fsBuilder->codeAppend(".rgb, ");
fsBuilder->appendTextureLookup(samplers[0], cCoords2);
// Premultiply color by alpha. Note that the input alpha is not modified by this shader.
fsBuilder->codeAppendf(".rgb, fract(%s.b)) * vec3(%s), %s.a);\n",
cubeIdx, nonZeroAlpha, inputColor);
}