GrBezierEffect.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * Copyright 2013 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef GrBezierEffect_DEFINED
  8. #define GrBezierEffect_DEFINED
  9. #include "include/private/GrTypesPriv.h"
  10. #include "src/gpu/GrCaps.h"
  11. #include "src/gpu/GrGeometryProcessor.h"
  12. #include "src/gpu/GrProcessor.h"
  13. /**
  14. * Shader is based off of Loop-Blinn Quadratic GPU Rendering
  15. * The output of this effect is a hairline edge for conics.
  16. * Conics specified by implicit equation K^2 - LM.
  17. * K, L, and M, are the first three values of the vertex attribute,
  18. * the fourth value is not used. Distance is calculated using a
  19. * first order approximation from the taylor series.
  20. * Coverage for AA is max(0, 1-distance).
  21. *
  22. * Test were also run using a second order distance approximation.
  23. * There were two versions of the second order approx. The first version
  24. * is of roughly the form:
  25. * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2.
  26. * The second is similar:
  27. * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2.
  28. * The exact version of the equations can be found in the paper
  29. * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin
  30. *
  31. * In both versions we solve the quadratic for ||q-p||.
  32. * Version 1:
  33. * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as derived from paper)
  34. * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2.0*gF2M);\n");
  35. * Version 2:
  36. * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2.0*gF2M);\n");
  37. *
  38. * Also note that 2nd partials of k,l,m are zero
  39. *
  40. * When comparing the two second order approximations to the first order approximations,
  41. * the following results were found. Version 1 tends to underestimate the distances, thus it
  42. * basically increases all the error that we were already seeing in the first order
  43. * approx. So this version is not the one to use. Version 2 has the opposite effect
  44. * and tends to overestimate the distances. This is much closer to what we are
  45. * looking for. It is able to render ellipses (even thin ones) without the need to chop.
  46. * However, it can not handle thin hyperbolas well and thus would still rely on
  47. * chopping to tighten the clipping. Another side effect of the overestimating is
  48. * that the curves become much thinner and "ropey". If all that was ever rendered
  49. * were "not too thin" curves and ellipses then 2nd order may have an advantage since
  50. * only one geometry would need to be rendered. However no benches were run comparing
  51. * chopped first order and non chopped 2nd order.
  52. */
  53. class GrGLConicEffect;
  54. class GrConicEffect : public GrGeometryProcessor {
  55. public:
  56. static sk_sp<GrGeometryProcessor> Make(const SkPMColor4f& color,
  57. const SkMatrix& viewMatrix,
  58. const GrClipEdgeType edgeType,
  59. const GrCaps& caps,
  60. const SkMatrix& localMatrix,
  61. bool usesLocalCoords,
  62. uint8_t coverage = 0xff) {
  63. switch (edgeType) {
  64. case GrClipEdgeType::kFillAA:
  65. if (!caps.shaderCaps()->shaderDerivativeSupport()) {
  66. return nullptr;
  67. }
  68. return sk_sp<GrGeometryProcessor>(
  69. new GrConicEffect(color, viewMatrix, coverage, GrClipEdgeType::kFillAA,
  70. localMatrix, usesLocalCoords));
  71. case GrClipEdgeType::kHairlineAA:
  72. if (!caps.shaderCaps()->shaderDerivativeSupport()) {
  73. return nullptr;
  74. }
  75. return sk_sp<GrGeometryProcessor>(
  76. new GrConicEffect(color, viewMatrix, coverage,
  77. GrClipEdgeType::kHairlineAA, localMatrix,
  78. usesLocalCoords));
  79. case GrClipEdgeType::kFillBW:
  80. return sk_sp<GrGeometryProcessor>(
  81. new GrConicEffect(color, viewMatrix, coverage, GrClipEdgeType::kFillBW,
  82. localMatrix, usesLocalCoords));
  83. default:
  84. return nullptr;
  85. }
  86. }
  87. ~GrConicEffect() override;
  88. const char* name() const override { return "Conic"; }
  89. inline const Attribute& inPosition() const { return kAttributes[0]; }
  90. inline const Attribute& inConicCoeffs() const { return kAttributes[1]; }
  91. inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
  92. inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
  93. inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
  94. const SkPMColor4f& color() const { return fColor; }
  95. const SkMatrix& viewMatrix() const { return fViewMatrix; }
  96. const SkMatrix& localMatrix() const { return fLocalMatrix; }
  97. bool usesLocalCoords() const { return fUsesLocalCoords; }
  98. uint8_t coverageScale() const { return fCoverageScale; }
  99. void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
  100. GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
  101. private:
  102. GrConicEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
  103. const SkMatrix& localMatrix, bool usesLocalCoords);
  104. SkPMColor4f fColor;
  105. SkMatrix fViewMatrix;
  106. SkMatrix fLocalMatrix;
  107. bool fUsesLocalCoords;
  108. uint8_t fCoverageScale;
  109. GrClipEdgeType fEdgeType;
  110. static constexpr Attribute kAttributes[] = {
  111. {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
  112. {"inConicCoeffs", kFloat4_GrVertexAttribType, kHalf4_GrSLType}
  113. };
  114. GR_DECLARE_GEOMETRY_PROCESSOR_TEST
  115. typedef GrGeometryProcessor INHERITED;
  116. };
  117. ///////////////////////////////////////////////////////////////////////////////
  118. /**
  119. * The output of this effect is a hairline edge for quadratics.
  120. * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
  121. * two components of the vertex attribute. At the three control points that define
  122. * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
  123. * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
  124. * Requires shader derivative instruction support.
  125. */
  126. class GrGLQuadEffect;
  127. class GrQuadEffect : public GrGeometryProcessor {
  128. public:
  129. static sk_sp<GrGeometryProcessor> Make(const SkPMColor4f& color,
  130. const SkMatrix& viewMatrix,
  131. const GrClipEdgeType edgeType,
  132. const GrCaps& caps,
  133. const SkMatrix& localMatrix,
  134. bool usesLocalCoords,
  135. uint8_t coverage = 0xff) {
  136. switch (edgeType) {
  137. case GrClipEdgeType::kFillAA:
  138. if (!caps.shaderCaps()->shaderDerivativeSupport()) {
  139. return nullptr;
  140. }
  141. return sk_sp<GrGeometryProcessor>(
  142. new GrQuadEffect(color, viewMatrix, coverage, GrClipEdgeType::kFillAA,
  143. localMatrix, usesLocalCoords));
  144. case GrClipEdgeType::kHairlineAA:
  145. if (!caps.shaderCaps()->shaderDerivativeSupport()) {
  146. return nullptr;
  147. }
  148. return sk_sp<GrGeometryProcessor>(
  149. new GrQuadEffect(color, viewMatrix, coverage,
  150. GrClipEdgeType::kHairlineAA, localMatrix,
  151. usesLocalCoords));
  152. case GrClipEdgeType::kFillBW:
  153. return sk_sp<GrGeometryProcessor>(
  154. new GrQuadEffect(color, viewMatrix, coverage, GrClipEdgeType::kFillBW,
  155. localMatrix, usesLocalCoords));
  156. default:
  157. return nullptr;
  158. }
  159. }
  160. ~GrQuadEffect() override;
  161. const char* name() const override { return "Quad"; }
  162. inline const Attribute& inPosition() const { return kAttributes[0]; }
  163. inline const Attribute& inHairQuadEdge() const { return kAttributes[1]; }
  164. inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
  165. inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
  166. inline GrClipEdgeType getEdgeType() const { return fEdgeType; }
  167. const SkPMColor4f& color() const { return fColor; }
  168. const SkMatrix& viewMatrix() const { return fViewMatrix; }
  169. const SkMatrix& localMatrix() const { return fLocalMatrix; }
  170. bool usesLocalCoords() const { return fUsesLocalCoords; }
  171. uint8_t coverageScale() const { return fCoverageScale; }
  172. void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
  173. GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
  174. private:
  175. GrQuadEffect(const SkPMColor4f&, const SkMatrix& viewMatrix, uint8_t coverage, GrClipEdgeType,
  176. const SkMatrix& localMatrix, bool usesLocalCoords);
  177. SkPMColor4f fColor;
  178. SkMatrix fViewMatrix;
  179. SkMatrix fLocalMatrix;
  180. bool fUsesLocalCoords;
  181. uint8_t fCoverageScale;
  182. GrClipEdgeType fEdgeType;
  183. static constexpr Attribute kAttributes[] = {
  184. {"inPosition", kFloat2_GrVertexAttribType, kFloat2_GrSLType},
  185. {"inHairQuadEdge", kFloat4_GrVertexAttribType, kHalf4_GrSLType}
  186. };
  187. GR_DECLARE_GEOMETRY_PROCESSOR_TEST
  188. typedef GrGeometryProcessor INHERITED;
  189. };
  190. #endif