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

Side by Side Diff: src/gpu/effects/GrDistanceFieldTextureEffect.cpp

Issue 1013773002: Fix SDF gradient calculation for non-uniform xforms (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix bugs and address comments Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « gm/dftext.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "GrDistanceFieldTextureEffect.h" 8 #include "GrDistanceFieldTextureEffect.h"
9 #include "GrFontAtlasSizes.h" 9 #include "GrFontAtlasSizes.h"
10 #include "GrInvariantOutput.h" 10 #include "GrInvariantOutput.h"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn()); 77 fsBuilder->codeAppendf("vec2 uv = %s;\n", uv.fsIn());
78 78
79 fsBuilder->codeAppend("\tfloat texColor = "); 79 fsBuilder->codeAppend("\tfloat texColor = ");
80 fsBuilder->appendTextureLookup(args.fSamplers[0], 80 fsBuilder->appendTextureLookup(args.fSamplers[0],
81 "uv", 81 "uv",
82 kVec2f_GrSLType); 82 kVec2f_GrSLType);
83 fsBuilder->codeAppend(".r;\n"); 83 fsBuilder->codeAppend(".r;\n");
84 fsBuilder->codeAppend("\tfloat distance = " 84 fsBuilder->codeAppend("\tfloat distance = "
85 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFie ldThreshold ");"); 85 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFie ldThreshold ");");
86 86
87 // we adjust for the effect of the transformation on the distance by usi ng
88 // the length of the gradient of the texture coordinates. We use st coor dinates
89 // to ensure we're mapping 1:1 from texel space to pixel space.
90 fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision , 87 fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision ,
91 pb->ctxInfo().stand ard())); 88 pb->ctxInfo().stand ard()));
92 fsBuilder->codeAppendf("vec2 st = %s;\n", st.fsIn()); 89 fsBuilder->codeAppendf("vec2 st = %s;", st.fsIn());
93 fsBuilder->codeAppend("\tfloat afwidth;\n"); 90 fsBuilder->codeAppend("float afwidth;");
94 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { 91 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
92 // For uniform scale, we adjust for the effect of the transformation on the distance
93 // by using the length of the gradient of the texture coordinates. W e use st coordinates
94 // to ensure we're mapping 1:1 from texel space to pixel space.
95
95 // this gives us a smooth step across approximately one fragment 96 // this gives us a smooth step across approximately one fragment
96 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "* dFdx(st.x));\n"); 97 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF dx(st.x));");
97 } else { 98 } else {
98 fsBuilder->codeAppend("\tvec2 Jdx = dFdx(st);\n"); 99 // For general transforms, to determine the amount of correction we multiply a unit
99 fsBuilder->codeAppend("\tvec2 Jdy = dFdy(st);\n"); 100 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
101 // (which is the inverse transform for this fragment) and take the l ength of the result.
robertphillips 2015/03/16 18:11:35 Move this computation down to where it is used?
jvanverth1 2015/03/16 18:17:40 Done.
102 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
103 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
100 104
101 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); 105 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(di stance));");
102 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { 106 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
103 // this is to compensate for the Adreno, which likes to drop til es on division by 0 107 // this is to compensate for the Adreno, which likes to drop til es on division by 0
104 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); 108 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad) ;");
105 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); 109 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
106 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); 110 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
107 fsBuilder->codeAppend("\t} else {\n"); 111 fsBuilder->codeAppend("} else {");
108 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" ); 112 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2 );");
109 fsBuilder->codeAppend("\t}\n"); 113 fsBuilder->codeAppend("}");
110 } else { 114 } else {
111 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); 115 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n");
112 } 116 }
113 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n"); 117 fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_gra d.y*Jdy.x,");
114 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n"); 118 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra d.y*Jdy.y);");
115 119
116 // this gives us a smooth step across approximately one fragment 120 // this gives us a smooth step across approximately one fragment
117 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng th(grad);\n"); 121 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length (grad);");
118 } 122 }
119 fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista nce);\n"); 123 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc e);");
120 124
121 #ifdef SK_GAMMA_APPLY_TO_A8 125 #ifdef SK_GAMMA_APPLY_TO_A8
122 // adjust based on gamma 126 // adjust based on gamma
123 const char* luminanceUniName = NULL; 127 const char* luminanceUniName = NULL;
124 // width, height, 1/(3*width) 128 // width, height, 1/(3*width)
125 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib ility, 129 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib ility,
126 kFloat_GrSLType, kDefault_GrSLPreci sion, 130 kFloat_GrSLType, kDefault_GrSLPreci sion,
127 "Luminance", &luminanceUniName); 131 "Luminance", &luminanceUniName);
128 132
129 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); 133 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName);
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); 365 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn());
362 366
363 fsBuilder->codeAppend("float texColor = "); 367 fsBuilder->codeAppend("float texColor = ");
364 fsBuilder->appendTextureLookup(args.fSamplers[0], 368 fsBuilder->appendTextureLookup(args.fSamplers[0],
365 "uv", 369 "uv",
366 kVec2f_GrSLType); 370 kVec2f_GrSLType);
367 fsBuilder->codeAppend(".r;"); 371 fsBuilder->codeAppend(".r;");
368 fsBuilder->codeAppend("float distance = " 372 fsBuilder->codeAppend("float distance = "
369 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");"); 373 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold ");");
370 374
371 // we adjust for the effect of the transformation on the distance by usi ng
372 // the length of the gradient of the texture coordinates. We use st coor dinates
373 // to ensure we're mapping 1:1 from texel space to pixel space.
374 fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision , 375 fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision ,
375 pb->ctxInfo().stand ard())); 376 pb->ctxInfo().stand ard()));
376 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); 377 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName);
377 fsBuilder->codeAppend("float afwidth;"); 378 fsBuilder->codeAppend("float afwidth;");
378 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { 379 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) {
380 // For uniform scale, we adjust for the effect of the transformation on the distance
381 // by using the length of the gradient of the texture coordinates. W e use st coordinates
382 // to ensure we're mapping 1:1 from texel space to pixel space.
383
379 // this gives us a smooth step across approximately one fragment 384 // this gives us a smooth step across approximately one fragment
380 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF dx(st.x));"); 385 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF dx(st.x));");
381 } else { 386 } else {
387 // For general transforms, to determine the amount of correction we multiply a unit
388 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
389 // (which is the inverse transform for this fragment) and take the l ength of the result.
robertphillips 2015/03/16 18:11:35 here too ?
jvanverth1 2015/03/16 18:17:41 Done.
382 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); 390 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);");
383 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); 391 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);");
384 392
385 fsBuilder->codeAppend("vec2 uv_grad;"); 393 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(di stance));");
386 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { 394 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
387 // this is to compensate for the Adreno, which likes to drop til es on division by 0 395 // this is to compensate for the Adreno, which likes to drop til es on division by 0
388 fsBuilder->codeAppend("float uv_len2 = dot(uv, uv);"); 396 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad) ;");
389 fsBuilder->codeAppend("if (uv_len2 < 0.0001) {"); 397 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
390 fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);"); 398 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
391 fsBuilder->codeAppend("} else {"); 399 fsBuilder->codeAppend("} else {");
392 fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);"); 400 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2 );");
393 fsBuilder->codeAppend("}"); 401 fsBuilder->codeAppend("}");
394 } else { 402 } else {
395 fsBuilder->codeAppend("uv_grad = normalize(uv);"); 403 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);");
396 } 404 }
397 fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y* Jdy.x,"); 405 fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_gra d.y*Jdy.x,");
398 fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y* Jdy.y);"); 406 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra d.y*Jdy.y);");
399 407
400 // this gives us a smooth step across approximately one fragment 408 // this gives us a smooth step across approximately one fragment
401 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length (grad);"); 409 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length (grad);");
402 } 410 }
403 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc e);"); 411 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc e);");
404 412
405 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); 413 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
406 } 414 }
407 415
408 virtual void setData(const GrGLProgramDataManager& pdman, 416 virtual void setData(const GrGLProgramDataManager& pdman,
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 // blue is distance to right offset 649 // blue is distance to right offset
642 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); 650 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n");
643 fsBuilder->codeAppend("\ttexColor = "); 651 fsBuilder->codeAppend("\ttexColor = ");
644 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_ GrSLType); 652 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_ GrSLType);
645 fsBuilder->codeAppend(";\n"); 653 fsBuilder->codeAppend(";\n");
646 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); 654 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n");
647 655
648 fsBuilder->codeAppend("\tdistance = " 656 fsBuilder->codeAppend("\tdistance = "
649 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF ieldThreshold"));"); 657 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF ieldThreshold"));");
650 658
651 // we adjust for the effect of the transformation on the distance by usi ng
652 // the length of the gradient of the texture coordinates. We use st coor dinates
653 // to ensure we're mapping 1:1 from texel space to pixel space.
654
655 // To be strictly correct, we should compute the anti-aliasing factor se parately 659 // To be strictly correct, we should compute the anti-aliasing factor se parately
656 // for each color component. However, this is only important when using perspective 660 // for each color component. However, this is only important when using perspective
657 // transformations, and even then using a single factor seems like a rea sonable 661 // transformations, and even then using a single factor seems like a rea sonable
658 // trade-off between quality and speed. 662 // trade-off between quality and speed.
659 fsBuilder->codeAppend("\tfloat afwidth;\n"); 663 fsBuilder->codeAppend("float afwidth;");
660 if (isUniformScale) { 664 if (isUniformScale) {
665 // For uniform scale, we adjust for the effect of the transformation on the distance
666 // by using the length of the gradient of the texture coordinates. W e use st coordinates
667 // to ensure we're mapping 1:1 from texel space to pixel space.
668
661 // this gives us a smooth step across approximately one fragment 669 // this gives us a smooth step across approximately one fragment
662 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "* dx);\n"); 670 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx );");
663 } else { 671 } else {
664 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); 672 // For general transforms, to determine the amount of correction we multiply a unit
673 // vector pointing along the SDF gradient direction by the Jacobian of the st coords
674 // (which is the inverse transform for this fragment) and take the l ength of the result.
675 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy( distance.r));");
665 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { 676 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) {
666 // this is to compensate for the Adreno, which likes to drop til es on division by 0 677 // this is to compensate for the Adreno, which likes to drop til es on division by 0
667 fsBuilder->codeAppend("\tfloat uv_len2 = dot(uv, uv);\n"); 678 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad) ;");
668 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); 679 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {");
669 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); 680 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);");
670 fsBuilder->codeAppend("\t} else {\n"); 681 fsBuilder->codeAppend("} else {");
671 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n" ); 682 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2 );");
672 fsBuilder->codeAppend("\t}\n"); 683 fsBuilder->codeAppend("}");
673 } else { 684 } else {
674 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); 685 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n");
675 } 686 }
676 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad. y*Jdy.x,\n"); 687 fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_gra d.y*Jdy.x,");
677 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad. y*Jdy.y);\n"); 688 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra d.y*Jdy.y);");
678 689
679 // this gives us a smooth step across approximately one fragment 690 // this gives us a smooth step across approximately one fragment
680 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng th(grad);\n"); 691 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length (grad);");
681 } 692 }
682 693
683 fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3 (afwidth), distance), 1.0);\n"); 694 fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(a fwidth), distance), 1.0);");
684 695
685 // adjust based on gamma 696 // adjust based on gamma
686 const char* textColorUniName = NULL; 697 const char* textColorUniName = NULL;
687 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib ility, 698 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib ility,
688 kVec3f_GrSLType, kDefault_GrSLPreci sion, 699 kVec3f_GrSLType, kDefault_GrSLPreci sion,
689 "TextColor", &textColorUniName); 700 "TextColor", &textColorUniName);
690 701
691 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); 702 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName);
692 fsBuilder->codeAppend("float gammaColor = "); 703 fsBuilder->codeAppend("float gammaColor = ");
693 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType) ; 704 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType) ;
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; 867 uint32_t flags = kUseLCD_DistanceFieldEffectFlag;
857 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; 868 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0;
858 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; 869 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
859 return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), 870 return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random),
860 GrProcessorUnitTest::TestMatr ix(random), 871 GrProcessorUnitTest::TestMatr ix(random),
861 textures[texIdx], params, 872 textures[texIdx], params,
862 textures[texIdx2], params2, 873 textures[texIdx2], params2,
863 textColor, 874 textColor,
864 flags); 875 flags);
865 } 876 }
OLDNEW
« no previous file with comments | « gm/dftext.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698