OLD | NEW |
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 Loading... |
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 |
100 | 101 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
101 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); | 102 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(di
stance));"); |
102 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { | 103 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
103 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 | 104 // 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"); | 105 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad)
;"); |
105 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); | 106 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
106 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); | 107 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
107 fsBuilder->codeAppend("\t} else {\n"); | 108 fsBuilder->codeAppend("} else {"); |
108 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); | 109 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2
);"); |
109 fsBuilder->codeAppend("\t}\n"); | 110 fsBuilder->codeAppend("}"); |
110 } else { | 111 } else { |
111 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); | 112 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n"); |
112 } | 113 } |
113 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); | 114 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
114 fsBuilder->codeAppend("\t uv_grad.x*Jdx.y + uv_grad.
y*Jdy.y);\n"); | 115 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
| 116 fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_gra
d.y*Jdy.x,"); |
| 117 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra
d.y*Jdy.y);"); |
115 | 118 |
116 // this gives us a smooth step across approximately one fragment | 119 // this gives us a smooth step across approximately one fragment |
117 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); | 120 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); |
118 } | 121 } |
119 fsBuilder->codeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista
nce);\n"); | 122 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc
e);"); |
120 | 123 |
121 #ifdef SK_GAMMA_APPLY_TO_A8 | 124 #ifdef SK_GAMMA_APPLY_TO_A8 |
122 // adjust based on gamma | 125 // adjust based on gamma |
123 const char* luminanceUniName = NULL; | 126 const char* luminanceUniName = NULL; |
124 // width, height, 1/(3*width) | 127 // width, height, 1/(3*width) |
125 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, | 128 fLuminanceUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, |
126 kFloat_GrSLType, kDefault_GrSLPreci
sion, | 129 kFloat_GrSLType, kDefault_GrSLPreci
sion, |
127 "Luminance", &luminanceUniName); | 130 "Luminance", &luminanceUniName); |
128 | 131 |
129 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); | 132 fsBuilder->codeAppendf("\tuv = vec2(val, %s);\n", luminanceUniName); |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); | 364 fsBuilder->codeAppendf("vec2 uv = %s;", v.fsIn()); |
362 | 365 |
363 fsBuilder->codeAppend("float texColor = "); | 366 fsBuilder->codeAppend("float texColor = "); |
364 fsBuilder->appendTextureLookup(args.fSamplers[0], | 367 fsBuilder->appendTextureLookup(args.fSamplers[0], |
365 "uv", | 368 "uv", |
366 kVec2f_GrSLType); | 369 kVec2f_GrSLType); |
367 fsBuilder->codeAppend(".r;"); | 370 fsBuilder->codeAppend(".r;"); |
368 fsBuilder->codeAppend("float distance = " | 371 fsBuilder->codeAppend("float distance = " |
369 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold
");"); | 372 SK_DistanceFieldMultiplier "*(texColor - " SK_DistanceFieldThreshold
");"); |
370 | 373 |
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
, | 374 fsBuilder->codeAppend(GrGLShaderVar::PrecisionString(kHigh_GrSLPrecision
, |
375 pb->ctxInfo().stand
ard())); | 375 pb->ctxInfo().stand
ard())); |
376 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); | 376 fsBuilder->codeAppendf("vec2 st = uv*%s;", textureSizeUniName); |
377 fsBuilder->codeAppend("float afwidth;"); | 377 fsBuilder->codeAppend("float afwidth;"); |
378 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { | 378 if (dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag) { |
| 379 // For uniform scale, we adjust for the effect of the transformation
on the distance |
| 380 // by using the length of the gradient of the texture coordinates. W
e use st coordinates |
| 381 // to ensure we're mapping 1:1 from texel space to pixel space. |
| 382 |
379 // this gives us a smooth step across approximately one fragment | 383 // this gives us a smooth step across approximately one fragment |
380 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF
dx(st.x));"); | 384 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dF
dx(st.x));"); |
381 } else { | 385 } else { |
| 386 // For general transforms, to determine the amount of correction we
multiply a unit |
| 387 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords |
| 388 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
| 389 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance), dFdy(di
stance));"); |
| 390 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
| 391 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 |
| 392 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad)
;"); |
| 393 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
| 394 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
| 395 fsBuilder->codeAppend("} else {"); |
| 396 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2
);"); |
| 397 fsBuilder->codeAppend("}"); |
| 398 } else { |
| 399 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);"); |
| 400 } |
382 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); | 401 fsBuilder->codeAppend("vec2 Jdx = dFdx(st);"); |
383 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); | 402 fsBuilder->codeAppend("vec2 Jdy = dFdy(st);"); |
384 | 403 fsBuilder->codeAppend("vec2 grad = vec2(dist_grad.x*Jdx.x + dist_gra
d.y*Jdy.x,"); |
385 fsBuilder->codeAppend("vec2 uv_grad;"); | 404 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra
d.y*Jdy.y);"); |
386 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { | |
387 // 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);"); | |
389 fsBuilder->codeAppend("if (uv_len2 < 0.0001) {"); | |
390 fsBuilder->codeAppend("uv_grad = vec2(0.7071, 0.7071);"); | |
391 fsBuilder->codeAppend("} else {"); | |
392 fsBuilder->codeAppend("uv_grad = uv*inversesqrt(uv_len2);"); | |
393 fsBuilder->codeAppend("}"); | |
394 } else { | |
395 fsBuilder->codeAppend("uv_grad = normalize(uv);"); | |
396 } | |
397 fsBuilder->codeAppend("vec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.y*
Jdy.x,"); | |
398 fsBuilder->codeAppend(" uv_grad.x*Jdx.y + uv_grad.y*
Jdy.y);"); | |
399 | 405 |
400 // this gives us a smooth step across approximately one fragment | 406 // this gives us a smooth step across approximately one fragment |
401 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); | 407 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); |
402 } | 408 } |
403 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc
e);"); | 409 fsBuilder->codeAppend("float val = smoothstep(-afwidth, afwidth, distanc
e);"); |
404 | 410 |
405 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); | 411 fsBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage); |
406 } | 412 } |
407 | 413 |
408 virtual void setData(const GrGLProgramDataManager& pdman, | 414 virtual void setData(const GrGLProgramDataManager& pdman, |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 // blue is distance to right offset | 647 // blue is distance to right offset |
642 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); | 648 fsBuilder->codeAppend("\tuv_adjusted = uv + offset;\n"); |
643 fsBuilder->codeAppend("\ttexColor = "); | 649 fsBuilder->codeAppend("\ttexColor = "); |
644 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); | 650 fsBuilder->appendTextureLookup(args.fSamplers[0], "uv_adjusted", kVec2f_
GrSLType); |
645 fsBuilder->codeAppend(";\n"); | 651 fsBuilder->codeAppend(";\n"); |
646 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); | 652 fsBuilder->codeAppend("\tdistance.z = texColor.r;\n"); |
647 | 653 |
648 fsBuilder->codeAppend("\tdistance = " | 654 fsBuilder->codeAppend("\tdistance = " |
649 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF
ieldThreshold"));"); | 655 "vec3(" SK_DistanceFieldMultiplier ")*(distance - vec3(" SK_DistanceF
ieldThreshold"));"); |
650 | 656 |
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 | 657 // 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 | 658 // 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 | 659 // transformations, and even then using a single factor seems like a rea
sonable |
658 // trade-off between quality and speed. | 660 // trade-off between quality and speed. |
659 fsBuilder->codeAppend("\tfloat afwidth;\n"); | 661 fsBuilder->codeAppend("float afwidth;"); |
660 if (isUniformScale) { | 662 if (isUniformScale) { |
| 663 // For uniform scale, we adjust for the effect of the transformation
on the distance |
| 664 // by using the length of the gradient of the texture coordinates. W
e use st coordinates |
| 665 // to ensure we're mapping 1:1 from texel space to pixel space. |
| 666 |
661 // this gives us a smooth step across approximately one fragment | 667 // this gives us a smooth step across approximately one fragment |
662 fsBuilder->codeAppend("\tafwidth = abs(" SK_DistanceFieldAAFactor "*
dx);\n"); | 668 fsBuilder->codeAppend("afwidth = abs(" SK_DistanceFieldAAFactor "*dx
);"); |
663 } else { | 669 } else { |
664 fsBuilder->codeAppend("\tvec2 uv_grad;\n"); | 670 // For general transforms, to determine the amount of correction we
multiply a unit |
| 671 // vector pointing along the SDF gradient direction by the Jacobian
of the st coords |
| 672 // (which is the inverse transform for this fragment) and take the l
ength of the result. |
| 673 fsBuilder->codeAppend("vec2 dist_grad = vec2(dFdx(distance.r), dFdy(
distance.r));"); |
665 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { | 674 if (args.fPB->ctxInfo().caps()->dropsTileOnZeroDivide()) { |
666 // this is to compensate for the Adreno, which likes to drop til
es on division by 0 | 675 // 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"); | 676 fsBuilder->codeAppend("float dg_len2 = dot(dist_grad, dist_grad)
;"); |
668 fsBuilder->codeAppend("\tif (uv_len2 < 0.0001) {\n"); | 677 fsBuilder->codeAppend("if (dg_len2 < 0.0001) {"); |
669 fsBuilder->codeAppend("\t\tuv_grad = vec2(0.7071, 0.7071);\n"); | 678 fsBuilder->codeAppend("dist_grad = vec2(0.7071, 0.7071);"); |
670 fsBuilder->codeAppend("\t} else {\n"); | 679 fsBuilder->codeAppend("} else {"); |
671 fsBuilder->codeAppend("\t\tuv_grad = uv*inversesqrt(uv_len2);\n"
); | 680 fsBuilder->codeAppend("dist_grad = dist_grad*inversesqrt(dg_len2
);"); |
672 fsBuilder->codeAppend("\t}\n"); | 681 fsBuilder->codeAppend("}"); |
673 } else { | 682 } else { |
674 fsBuilder->codeAppend("\tuv_grad = normalize(uv);\n"); | 683 fsBuilder->codeAppend("dist_grad = normalize(dist_grad);\n"); |
675 } | 684 } |
676 fsBuilder->codeAppend("\tvec2 grad = vec2(uv_grad.x*Jdx.x + uv_grad.
y*Jdy.x,\n"); | 685 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"); | 686 fsBuilder->codeAppend(" dist_grad.x*Jdx.y + dist_gra
d.y*Jdy.y);"); |
678 | 687 |
679 // this gives us a smooth step across approximately one fragment | 688 // this gives us a smooth step across approximately one fragment |
680 fsBuilder->codeAppend("\tafwidth = " SK_DistanceFieldAAFactor "*leng
th(grad);\n"); | 689 fsBuilder->codeAppend("afwidth = " SK_DistanceFieldAAFactor "*length
(grad);"); |
681 } | 690 } |
682 | 691 |
683 fsBuilder->codeAppend("\tvec4 val = vec4(smoothstep(vec3(-afwidth), vec3
(afwidth), distance), 1.0);\n"); | 692 fsBuilder->codeAppend("vec4 val = vec4(smoothstep(vec3(-afwidth), vec3(a
fwidth), distance), 1.0);"); |
684 | 693 |
685 // adjust based on gamma | 694 // adjust based on gamma |
686 const char* textColorUniName = NULL; | 695 const char* textColorUniName = NULL; |
687 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, | 696 fTextColorUni = args.fPB->addUniform(GrGLProgramBuilder::kFragment_Visib
ility, |
688 kVec3f_GrSLType, kDefault_GrSLPreci
sion, | 697 kVec3f_GrSLType, kDefault_GrSLPreci
sion, |
689 "TextColor", &textColorUniName); | 698 "TextColor", &textColorUniName); |
690 | 699 |
691 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); | 700 fsBuilder->codeAppendf("\tuv = vec2(val.x, %s.x);\n", textColorUniName); |
692 fsBuilder->codeAppend("float gammaColor = "); | 701 fsBuilder->codeAppend("float gammaColor = "); |
693 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; | 702 fsBuilder->appendTextureLookup(args.fSamplers[1], "uv", kVec2f_GrSLType)
; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
856 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; | 865 uint32_t flags = kUseLCD_DistanceFieldEffectFlag; |
857 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; | 866 flags |= random->nextBool() ? kUniformScale_DistanceFieldEffectMask : 0; |
858 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; | 867 flags |= random->nextBool() ? kBGR_DistanceFieldEffectFlag : 0; |
859 return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), | 868 return GrDistanceFieldLCDTextureEffect::Create(GrRandomColor(random), |
860 GrProcessorUnitTest::TestMatr
ix(random), | 869 GrProcessorUnitTest::TestMatr
ix(random), |
861 textures[texIdx], params, | 870 textures[texIdx], params, |
862 textures[texIdx2], params2, | 871 textures[texIdx2], params2, |
863 textColor, | 872 textColor, |
864 flags); | 873 flags); |
865 } | 874 } |
OLD | NEW |