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 "gl/GrGLEffect.h" | 9 #include "gl/GrGLEffect.h" |
10 #include "gl/GrGLSL.h" | 10 #include "gl/GrGLSL.h" |
11 #include "gl/GrGLTexture.h" | 11 #include "gl/GrGLTexture.h" |
12 #include "gl/GrGLVertexEffect.h" | 12 #include "gl/GrGLVertexEffect.h" |
13 #include "GrTBackendEffectFactory.h" | 13 #include "GrTBackendEffectFactory.h" |
14 #include "GrTexture.h" | 14 #include "GrTexture.h" |
15 | 15 |
16 // The distance field is constructed as unsigned char values, so that the zero v
alue is at 128. | 16 // The distance field is constructed as unsigned char values, so that the zero v
alue is at 128, |
17 // Hence our zero threshold is 128/255. | 17 // and the range is [-4, 4 - 1/255). Hence our multiplier is 8 - 1/32 and zero t
hreshold is 128/255. |
| 18 #define MULTIPLIER "7.96875" |
18 #define THRESHOLD "0.50196078431" | 19 #define THRESHOLD "0.50196078431" |
19 | 20 |
20 class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect { | 21 class GrGLDistanceFieldTextureEffect : public GrGLVertexEffect { |
21 public: | 22 public: |
22 GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, const
GrDrawEffect& drawEffect) | 23 GrGLDistanceFieldTextureEffect(const GrBackendEffectFactory& factory, |
23 : INHERITED (factory) {} | 24 const GrDrawEffect& drawEffect) |
| 25 : INHERITED (factory) |
| 26 , fTextureSize(SkSize::Make(-1.f,-1.f)) {} |
24 | 27 |
25 virtual void emitCode(GrGLFullShaderBuilder* builder, | 28 virtual void emitCode(GrGLFullShaderBuilder* builder, |
26 const GrDrawEffect& drawEffect, | 29 const GrDrawEffect& drawEffect, |
27 EffectKey key, | 30 EffectKey key, |
28 const char* outputColor, | 31 const char* outputColor, |
29 const char* inputColor, | 32 const char* inputColor, |
30 const TransformedCoordsArray&, | 33 const TransformedCoordsArray&, |
31 const TextureSamplerArray& samplers) SK_OVERRIDE { | 34 const TextureSamplerArray& samplers) SK_OVERRIDE { |
32 SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numV
ertexAttribs()); | 35 SkASSERT(1 == drawEffect.castEffect<GrDistanceFieldTextureEffect>().numV
ertexAttribs()); |
33 | 36 |
| 37 SkAssertResult(builder->enableFeature(GrGLShaderBuilder::kStandardDeriva
tives_GLSLFeature)); |
| 38 |
34 SkString fsCoordName; | 39 SkString fsCoordName; |
35 const char* vsVaryingName; | 40 const char* vsCoordName; |
36 const char* fsVaryingNamePtr; | 41 const char* fsCoordNamePtr; |
37 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsVaryingName, &f
sVaryingNamePtr); | 42 builder->addVarying(kVec2f_GrSLType, "textureCoords", &vsCoordName, &fsC
oordNamePtr); |
38 fsCoordName = fsVaryingNamePtr; | 43 fsCoordName = fsCoordNamePtr; |
39 | 44 |
40 const char* attrName = | 45 const char* attrName0 = |
41 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[
0])->c_str(); | 46 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[
0])->c_str(); |
42 builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, attrName); | 47 builder->vsCodeAppendf("\t%s = %s;\n", vsCoordName, attrName0); |
| 48 |
| 49 const char* textureSizeUniName = NULL; |
| 50 fTextureSizeUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visib
ility, |
| 51 kVec2f_GrSLType, "TextureSize", |
| 52 &textureSizeUniName); |
43 | 53 |
44 builder->fsCodeAppend("\tvec4 texColor = "); | 54 builder->fsCodeAppend("\tvec4 texColor = "); |
45 builder->fsAppendTextureLookup(samplers[0], | 55 builder->fsAppendTextureLookup(samplers[0], |
46 fsCoordName.c_str(), | 56 fsCoordName.c_str(), |
47 kVec2f_GrSLType); | 57 kVec2f_GrSLType); |
48 builder->fsCodeAppend(";\n"); | 58 builder->fsCodeAppend(";\n"); |
49 builder->fsCodeAppend("\tfloat distance = texColor.r;\n"); | 59 builder->fsCodeAppend("\tfloat distance = "MULTIPLIER"*(texColor.r - "TH
RESHOLD");\n"); |
| 60 |
| 61 // we adjust for the effect of the transformation on the distance by usi
ng |
| 62 // the length of the gradient of the texture coordinates. We use st coor
dinates |
| 63 // to ensure we're mapping 1:1 from texel space to pixel space. |
| 64 builder->fsCodeAppendf("\tvec2 st = %s*%s;\n", fsCoordName.c_str(), text
ureSizeUniName); |
| 65 builder->fsCodeAppend("\tvec2 Jdx = dFdx(st);\n"); |
| 66 builder->fsCodeAppend("\tvec2 Jdy = dFdy(st);\n"); |
| 67 builder->fsCodeAppend("\tvec2 st_grad = normalize(st);\n"); |
| 68 builder->fsCodeAppend("\tvec2 grad = vec2(st_grad.x*Jdx.x + st_grad.y*Jd
y.x,\n"); |
| 69 builder->fsCodeAppend("\t st_grad.x*Jdx.y + st_grad.y*Jd
y.y);\n"); |
| 70 |
50 // this gives us a smooth step across approximately one fragment | 71 // this gives us a smooth step across approximately one fragment |
51 // (assuming a radius of the diagonal of the fragment, hence a factor of
sqrt(2)/2) | 72 // (assuming a radius of the diagonal of the fragment, hence a factor of
sqrt(2)/2) |
52 builder->fsCodeAppend("\tfloat afwidth = 0.7071*length(vec2(dFdx(distanc
e), dFdy(distance)));\n"); | 73 builder->fsCodeAppend("\tfloat afwidth = 0.7071*length(grad);\n"); |
53 builder->fsCodeAppend("\tfloat val = smoothstep("THRESHOLD"-afwidth, "TH
RESHOLD"+afwidth, distance);\n"); | 74 builder->fsCodeAppend("\tfloat val = smoothstep(-afwidth, afwidth, dista
nce);\n"); |
54 | 75 |
55 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, | 76 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, |
56 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")
).c_str()); | 77 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("val")
).c_str()); |
57 } | 78 } |
58 | 79 |
59 virtual void setData(const GrGLUniformManager& uman, | 80 virtual void setData(const GrGLUniformManager& uman, |
60 const GrDrawEffect& drawEffect) SK_OVERRIDE {} | 81 const GrDrawEffect& drawEffect) SK_OVERRIDE { |
| 82 SkASSERT(fTextureSizeUni.isValid()); |
| 83 const GrDistanceFieldTextureEffect& distanceFieldEffect = |
| 84 drawEffect.castEffect<GrDistanceFi
eldTextureEffect>(); |
| 85 if (distanceFieldEffect.getSize().width() != fTextureSize.width() || |
| 86 distanceFieldEffect.getSize().height() != fTextureSize.height()) { |
| 87 fTextureSize = distanceFieldEffect.getSize(); |
| 88 uman.set2f(fTextureSizeUni, |
| 89 distanceFieldEffect.getSize().width(), |
| 90 distanceFieldEffect.getSize().height()); |
| 91 } |
| 92 } |
61 | 93 |
62 private: | 94 private: |
| 95 GrGLUniformManager::UniformHandle fTextureSizeUni; |
| 96 SkSize fTextureSize; |
| 97 |
63 typedef GrGLVertexEffect INHERITED; | 98 typedef GrGLVertexEffect INHERITED; |
64 }; | 99 }; |
65 | 100 |
66 /////////////////////////////////////////////////////////////////////////////// | 101 /////////////////////////////////////////////////////////////////////////////// |
67 | 102 |
68 GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, | 103 GrDistanceFieldTextureEffect::GrDistanceFieldTextureEffect(GrTexture* texture, |
69 const GrTextureParams&
params) | 104 const GrTextureParams
& params, |
70 : fTextureAccess(texture, params) { | 105 const SkISize& size) |
| 106 : fTextureAccess(texture, params) |
| 107 , fSize(SkSize::Make(SkIntToScalar(size.width()), SkIntToScalar(size.height(
)))) { |
71 this->addTextureAccess(&fTextureAccess); | 108 this->addTextureAccess(&fTextureAccess); |
72 this->addVertexAttrib(kVec2f_GrSLType); | 109 this->addVertexAttrib(kVec2f_GrSLType); |
73 } | 110 } |
74 | 111 |
75 bool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const { | 112 bool GrDistanceFieldTextureEffect::onIsEqual(const GrEffect& other) const { |
76 const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureE
ffect>(other); | 113 const GrDistanceFieldTextureEffect& cte = CastEffect<GrDistanceFieldTextureE
ffect>(other); |
77 return fTextureAccess == cte.fTextureAccess; | 114 return fTextureAccess == cte.fTextureAccess; |
78 } | 115 } |
79 | 116 |
80 void GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color, | 117 void GrDistanceFieldTextureEffect::getConstantColorComponents(GrColor* color, |
(...skipping 24 matching lines...) Expand all Loading... |
105 SkShader::kClamp_TileMode, | 142 SkShader::kClamp_TileMode, |
106 SkShader::kRepeat_TileMode, | 143 SkShader::kRepeat_TileMode, |
107 SkShader::kMirror_TileMode, | 144 SkShader::kMirror_TileMode, |
108 }; | 145 }; |
109 SkShader::TileMode tileModes[] = { | 146 SkShader::TileMode tileModes[] = { |
110 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 147 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
111 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], | 148 kTileModes[random->nextULessThan(SK_ARRAY_COUNT(kTileModes))], |
112 }; | 149 }; |
113 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil
erp_FilterMode : | 150 GrTextureParams params(tileModes, random->nextBool() ? GrTextureParams::kBil
erp_FilterMode : |
114 GrTextureParams::kNon
e_FilterMode); | 151 GrTextureParams::kNon
e_FilterMode); |
| 152 SkISize size = SkISize::Make(1024, 2048); |
115 | 153 |
116 return GrDistanceFieldTextureEffect::Create(textures[texIdx], params); | 154 return GrDistanceFieldTextureEffect::Create(textures[texIdx], params, size); |
117 } | 155 } |
OLD | NEW |