diff options
author | jvanverth <jvanverth@google.com> | 2015-03-16 11:32:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-16 11:32:49 -0700 |
commit | 354eba5cb61801130a84378356434d3cc0a4b71a (patch) | |
tree | 8a9b58d43ebf04d7f02d6d5ffc62affa08b2cae9 /src/gpu/effects | |
parent | dfdec78a5d02e8690998741a9fe5b71a08ca3232 (diff) |
Fix SDF gradient calculation for non-uniform xforms
Also adds two non-uniform test cases to the dftext GM.
BUG=skia:3540
Review URL: https://codereview.chromium.org/1013773002
Diffstat (limited to 'src/gpu/effects')
-rwxr-xr-x | src/gpu/effects/GrDistanceFieldTextureEffect.cpp | 115 |
1 files changed, 62 insertions, 53 deletions
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index 89a634c5c4..c1c84b5871 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -84,39 +84,42 @@ public: fsBuilder->codeAppend("\tfloat distance = " SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); - // 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. fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, pb->ctxInfo().standard())); - fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); - fsBuilder->codeAppend("\tfloat afwidth;\n"); + fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn()); + fsBuilder->codeAppend("float afwidth;"); if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { + // 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 - fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));\n"); + fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));"); } else { - fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); - fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); - - fsBuilder->codeAppend("\tvec2 uv_grad;\n"); + // 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));"); if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { // this is to compensate for the Adreno, which likes to drop tiles on division by 0 - fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); - fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); - fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); - fsBuilder->codeAppend("\t} else {\n"); - fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); - fsBuilder->codeAppend("\t}\n"); + 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("}"); } else { - fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); + fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n"); } - fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); - fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); + fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); + fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); + fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); + fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); // this gives us a smooth step across approximately one fragment - fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); } - fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, distance);\n"); + fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distance);"); #ifdef SK_GAMMA_APPLY_TO_A8 // adjust based on gamma @@ -368,34 +371,37 @@ public: fsBuilder->codeAppend("float distance = " SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); - // 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. fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision, pb->ctxInfo().standard())); fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); fsBuilder->codeAppend("float afwidth;"); if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { + // 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 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dFdx(st.x));"); } else { - fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); - fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); - - fsBuilder->codeAppend("vec2 uv_grad;"); + // 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));"); if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { // this is to compensate for the Adreno, which likes to drop tiles on division by 0 - fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);"); - fsBuilder->codeAppend("if (uv_len2 < 0.0001) {"); - fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);"); + 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("uv_grad = uv*inversesqrt(uv_len2);"); + fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2);"); fsBuilder->codeAppend("}"); } else { - fsBuilder->codeAppend("uv_grad = normalize(uv);"); + fsBuilder->codeAppend("dist_grad = normalize(dist_grad);"); } - fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,"); - fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);"); + fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); + fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); + fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); + fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); // this gives us a smooth step across approximately one fragment fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); @@ -648,39 +654,42 @@ public: fsBuilder->codeAppend("\tdistance = " "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceFieldThreshold"));"); - // 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. - // To be strictly correct, we should compute the anti-aliasing factor separately // for each color component. However, this is only important when using perspective // transformations, and even then using a single factor seems like a reasonable // trade-off between quality and speed. - fsBuilder->codeAppend("\tfloat afwidth;\n"); + fsBuilder->codeAppend("float afwidth;"); if (isUniformScale) { + // 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 - fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*dx);\n"); + fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx);"); } else { - fsBuilder->codeAppend("\tvec2 uv_grad;\n"); + // 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.r), dFdy(distance.r));"); if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { // this is to compensate for the Adreno, which likes to drop tiles on division by 0 - fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); - fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); - fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); - fsBuilder->codeAppend("\t} else {\n"); - fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"); - fsBuilder->codeAppend("\t}\n"); + 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("}"); } else { - fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); + fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n"); } - fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*Jdy.x,\n"); - fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.y*Jdy.y);\n"); + fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_grad.y*Jdy.x,"); + fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_grad.y*Jdy.y);"); // this gives us a smooth step across approximately one fragment - fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*length(grad);\n"); + fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length(grad);"); } - fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);\n"); + fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(afwidth), distance), 1.0);"); // adjust based on gamma const char* textColorUniName = NULL; |