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

Side by Side Diff: src/gpu/GrAAHairLinePathRenderer.cpp

Issue 21036008: Add Loop Blinn hairline conics to GPU (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « samplecode/SampleHairCurves.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
2 /* 1 /*
3 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
4 * 3 *
5 * 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
6 * found in the LICENSE file. 5 * found in the LICENSE file.
7 */ 6 */
8 7
9 #include "GrAAHairLinePathRenderer.h" 8 #include "GrAAHairLinePathRenderer.h"
10 9
11 #include "GrContext.h" 10 #include "GrContext.h"
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 #endif 140 #endif
142 const int* iptr = (const int*)&x; 141 const int* iptr = (const int*)&x;
143 return (((*iptr) & 0x7f800000) >> 23) - 127; 142 return (((*iptr) & 0x7f800000) >> 23) - 127;
144 } 143 }
145 144
146 // Uses the max curvature function for quads to estimate 145 // Uses the max curvature function for quads to estimate
147 // where to chop the conic. If the max curvature is not 146 // where to chop the conic. If the max curvature is not
148 // found along the curve segment it will return 1 and 147 // found along the curve segment it will return 1 and
149 // dst[0] is the orginal conic. If it returns 2 the dst[0] 148 // dst[0] is the orginal conic. If it returns 2 the dst[0]
150 // and dst[1] are the two new conics. 149 // and dst[1] are the two new conics.
151 int chop_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) { 150 int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weight) {
152 SkScalar t = SkFindQuadMaxCurvature(src); 151 SkScalar t = SkFindQuadMaxCurvature(src);
153 if (t == 0) { 152 if (t == 0) {
154 if (dst) { 153 if (dst) {
155 dst[0].set(src, weight); 154 dst[0].set(src, weight);
156 } 155 }
157 return 1; 156 return 1;
158 } else { 157 } else {
159 if (dst) { 158 if (dst) {
160 SkConic conic; 159 SkConic conic;
161 conic.set(src, weight); 160 conic.set(src, weight);
162 conic.chopAt(t, dst); 161 conic.chopAt(t, dst);
163 } 162 }
164 return 2; 163 return 2;
165 } 164 }
166 } 165 }
167 166
167 // Calls split_conic on the entire conic and then once more on each subsection.
168 // Most cases will result in etiher 1 conic (chop point is not within t range)
jvanverth1 2013/07/31 18:41:40 Typos
169 // or 3 points (split onces and then once subsection split again).
170 int chop_conic(const SkPoint src[3], SkConic dst[4], const SkScalar weight) {
171 SkConic dstTemp[2];
172 int conicCnt = split_conic(src, dstTemp, weight);
173 if (2 == conicCnt){
174 int conicCnt2 = split_conic(dstTemp[0].fPts, dst, dstTemp[0].fW);
175 conicCnt = conicCnt2 + split_conic(dstTemp[1].fPts, &dst[conicCnt2], dst Temp[1].fW);
176 } else {
177 dst[0] = dstTemp[0];
178 }
179 return conicCnt;
180 }
181
168 // returns 0 if quad/conic is degen or close to it 182 // returns 0 if quad/conic is degen or close to it
169 // in this case approx the path with lines 183 // in this case approx the path with lines
170 // otherwise returns 1 184 // otherwise returns 1
171 int is_degen_quad_or_conic(const SkPoint p[3]) { 185 int is_degen_quad_or_conic(const SkPoint p[3]) {
172 static const SkScalar gDegenerateToLineTol = SK_Scalar1; 186 static const SkScalar gDegenerateToLineTol = SK_Scalar1;
173 static const SkScalar gDegenerateToLineTolSqd = 187 static const SkScalar gDegenerateToLineTolSqd =
174 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol); 188 SkScalarMul(gDegenerateToLineTol, gDegenerateToLineTol);
175 189
176 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd || 190 if (p[0].distanceToSqd(p[1]) < gDegenerateToLineTolSqd ||
177 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) { 191 p[1].distanceToSqd(p[2]) < gDegenerateToLineTolSqd) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 SkIRect ibounds; 278 SkIRect ibounds;
265 279
266 bool persp = m.hasPerspective(); 280 bool persp = m.hasPerspective();
267 281
268 for (;;) { 282 for (;;) {
269 GrPoint pathPts[4]; 283 GrPoint pathPts[4];
270 GrPoint devPts[4]; 284 GrPoint devPts[4];
271 SkPath::Verb verb = iter.next(pathPts); 285 SkPath::Verb verb = iter.next(pathPts);
272 switch (verb) { 286 switch (verb) {
273 case SkPath::kConic_Verb: { 287 case SkPath::kConic_Verb: {
274 SkConic dst[2]; 288 SkConic dst[4];
289 // We chop the conics to create tighter clipping to hide error
290 // that appears near max curvature of very thin conics. Thin
291 // hyperbolas with high weight still show error.
275 int conicCnt = chop_conic(pathPts, dst, iter.conicWeight()); 292 int conicCnt = chop_conic(pathPts, dst, iter.conicWeight());
276 for (int i = 0; i < conicCnt; ++i) { 293 for (int i = 0; i < conicCnt; ++i) {
277 SkPoint* chopPnts = dst[i].fPts; 294 SkPoint* chopPnts = dst[i].fPts;
278 m.mapPoints(devPts, chopPnts, 3); 295 m.mapPoints(devPts, chopPnts, 3);
279 bounds.setBounds(devPts, 3); 296 bounds.setBounds(devPts, 3);
280 bounds.outset(SK_Scalar1, SK_Scalar1); 297 bounds.outset(SK_Scalar1, SK_Scalar1);
281 bounds.roundOut(&ibounds); 298 bounds.roundOut(&ibounds);
282 if (SkIRect::Intersects(devClipBounds, ibounds)) { 299 if (SkIRect::Intersects(devClipBounds, ibounds)) {
283 if (is_degen_quad_or_conic(devPts)) { 300 if (is_degen_quad_or_conic(devPts)) {
284 SkPoint* pts = lines->push_back_n(4); 301 SkPoint* pts = lines->push_back_n(4);
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 434
418 struct Vertex { 435 struct Vertex {
419 GrPoint fPos; 436 GrPoint fPos;
420 union { 437 union {
421 struct { 438 struct {
422 SkScalar fA; 439 SkScalar fA;
423 SkScalar fB; 440 SkScalar fB;
424 SkScalar fC; 441 SkScalar fC;
425 } fLine; 442 } fLine;
426 struct { 443 struct {
427 SkScalar fA; 444 SkScalar fK;
428 SkScalar fB; 445 SkScalar fL;
429 SkScalar fC; 446 SkScalar fM;
430 SkScalar fD;
431 SkScalar fE;
432 SkScalar fF;
433 } fConic; 447 } fConic;
434 GrVec fQuadCoord; 448 GrVec fQuadCoord;
435 struct { 449 struct {
436 SkScalar fBogus[6]; 450 SkScalar fBogus[4];
437 }; 451 };
438 }; 452 };
439 }; 453 };
440 454
441 GR_STATIC_ASSERT(sizeof(Vertex) == 4 * sizeof(GrPoint)); 455 GR_STATIC_ASSERT(sizeof(Vertex) == 3 * sizeof(GrPoint));
442 456
443 void intersect_lines(const SkPoint& ptA, const SkVector& normA, 457 void intersect_lines(const SkPoint& ptA, const SkVector& normA,
444 const SkPoint& ptB, const SkVector& normB, 458 const SkPoint& ptB, const SkVector& normB,
445 SkPoint* result) { 459 SkPoint* result) {
446 460
447 SkScalar lineAW = -normA.dot(ptA); 461 SkScalar lineAW = -normA.dot(ptA);
448 SkScalar lineBW = -normB.dot(ptB); 462 SkScalar lineBW = -normB.dot(ptB);
449 463
450 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) - 464 SkScalar wInv = SkScalarMul(normA.fX, normB.fY) -
451 SkScalarMul(normA.fY, normB.fX); 465 SkScalarMul(normA.fY, normB.fX);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 // include it. 545 // include it.
532 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos); 546 intersect_lines(a0.fPos, abN, c0.fPos, cbN, &b0.fPos);
533 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY); 547 devBounds->growToInclude(b0.fPos.fX, b0.fPos.fY);
534 548
535 if (toSrc) { 549 if (toSrc) {
536 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad ); 550 toSrc->mapPointsWithStride(&verts[0].fPos, sizeof(Vertex), kVertsPerQuad );
537 } 551 }
538 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts); 552 DevToUV.apply<kVertsPerQuad, sizeof(Vertex), sizeof(GrPoint)>(verts);
539 } 553 }
540 554
555 // Input:
556 // Three control points: p[0], p[1], p[2] and weight: w
557 // Output:
558 // Let:
559 // l = (2*w * (y1 - y0), 2*w * (x0 - x1), 2*w * (x1*y0 - x0*y1))
560 // m = (2*w * (y2 - y1), 2*w * (x1 - x2), 2*w * (x2*y1 - x1*y2))
561 // k = (y2 - y0, x0 - x2, (x2 - x0)*y0 - (y2 - y0)*x0 )
562 void calc_conic_klm(const SkPoint p[3], const SkScalar weight,
563 SkScalar k[3], SkScalar l[3], SkScalar m[3]) {
541 564
565 const SkScalar w2 = 2 * weight;
566 l[0] = w2 * (p[1].fY - p[0].fY);
567 l[1] = w2 * (p[0].fX - p[1].fX);
568 l[2] = w2 * (p[1].fX * p[0].fY - p[0].fX * p[1].fY);
569
570 m[0] = w2 * (p[2].fY - p[1].fY);
571 m[1] = w2 * (p[1].fX - p[2].fX);
572 m[2] = w2 * (p[2].fX * p[1].fY - p[1].fX * p[2].fY);
573
574 k[0] = p[2].fY - p[0].fY;
575 k[1] = p[0].fX - p[2].fX;
576 k[2] = (p[2].fX - p[0].fX) * p[0].fY - (p[2].fY - p[0].fY) * p[0].fX;
577
578 // scale the max absolute value of coeffs to 10
579 SkScalar scale = 0.0f;
580 for (int i = 0; i < 3; ++i) {
581 scale = SkMaxScalar(scale, SkScalarAbs(k[i]));
582 scale = SkMaxScalar(scale, SkScalarAbs(l[i]));
583 scale = SkMaxScalar(scale, SkScalarAbs(m[i]));
584 }
585 GrAssert(scale > 0);
586 scale /= 10.0f;
587 k[0] /= scale;
588 k[1] /= scale;
589 k[2] /= scale;
590 l[0] /= scale;
591 l[1] /= scale;
592 l[2] /= scale;
593 m[0] /= scale;
594 m[1] /= scale;
595 m[2] /= scale;
596 }
597
598 // Equations based off of Loop-Blinn Quadradic GPU Rendering
542 // Input Parametric: 599 // Input Parametric:
543 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2) 600 // P(t) = (P0*(1-t)^2 + 2*w*P1*t*(1-t) + P2*t^2) / (1-t)^2 + 2*w*t*(1-t) + t^2)
544 // Output Implicit: 601 // Output Implicit:
545 // Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0 602 // f(x, y, w) = f(P) = K^2 - LM
546 // A = 4w^2*(y0-y1)(y1-y2)-(y0-y2)^2 603 // K = dot(k, P), L = dot(l, P), M = dot(m, P)
547 // B = 4w^2*((x0-x1)(y2-y1)+(x1-x2)(y1-y0)) + 2(x0-x2)(y0-y2) 604 // k, l, m are calculated in function calc_conic_klm
548 // C = 4w^2(x0-x1)(x1-x2) - (x0-x2)^2 605 void set_conic_coeffs(const SkPoint p[3], Vertex verts[kVertsPerQuad], const flo at weight) {
549 // D = 4w^2((x0y1-x1y0)(y1-y2)+(x1y2-x2y1)(y0-y1)) + 2(y2-y0)(x0y2-x2y0) 606 SkScalar k[3];
550 // E = 4w^2((y0x1-y1x0)(x1-x2)+(y1x2-y2x1)(x0-x1)) + 2(x2-x0)(y0x2-y2x0) 607 SkScalar l[3];
551 // F = 4w^2(x1y2-x2y1)(x0y1-x1y0) - (x2y0-x0y2)^2 608 SkScalar m[3];
552 609
553 void set_conic_coeffs(const SkPoint p[3], Vertex verts[kVertsPerQuad], const flo at weight) { 610 calc_conic_klm(p, weight, k, l, m);
554 const float ww4 = 4 * weight * weight;
555 const float x0Mx1 = p[0].fX - p[1].fX;
556 const float x1Mx2 = p[1].fX - p[2].fX;
557 const float x0Mx2 = p[0].fX - p[2].fX;
558 const float y0My1 = p[0].fY - p[1].fY;
559 const float y1My2 = p[1].fY - p[2].fY;
560 const float y0My2 = p[0].fY - p[2].fY;
561 const float x0y1Mx1y0 = p[0].fX*p[1].fY - p[1].fX*p[0].fY;
562 const float x1y2Mx2y1 = p[1].fX*p[2].fY - p[2].fX*p[1].fY;
563 const float x0y2Mx2y0 = p[0].fX*p[2].fY - p[2].fX*p[0].fY;
564 const float a = ww4 * y0My1 * y1My2 - y0My2 * y0My2;
565 const float b = -ww4 * (x0Mx1 * y1My2 + x1Mx2 * y0My1) + 2 * x0Mx2 * y0My2;
566 const float c = ww4 * x0Mx1 * x1Mx2 - x0Mx2 * x0Mx2;
567 const float d = ww4 * (x0y1Mx1y0 * y1My2 + x1y2Mx2y1 * y0My1) - 2 * y0My2 * x0y2Mx2y0;
568 const float e = -ww4 * (x0y1Mx1y0 * x1Mx2 + x1y2Mx2y1 * x0Mx1) + 2 * x0Mx2 * x0y2Mx2y0;
569 const float f = ww4 * x1y2Mx2y1 * x0y1Mx1y0 - x0y2Mx2y0 * x0y2Mx2y0;
570 611
571 for (int i = 0; i < kVertsPerQuad; ++i) { 612 for (int i = 0; i < kVertsPerQuad; ++i) {
572 verts[i].fConic.fA = a/f; 613 const SkPoint pnt = verts[i].fPos;
573 verts[i].fConic.fB = b/f; 614 verts[i].fConic.fK = pnt.fX * k[0] + pnt.fY * k[1] + k[2];
574 verts[i].fConic.fC = c/f; 615 verts[i].fConic.fL = pnt.fX * l[0] + pnt.fY * l[1] + l[2];
575 verts[i].fConic.fD = d/f; 616 verts[i].fConic.fM = pnt.fX * m[0] + pnt.fY * m[1] + m[2];
576 verts[i].fConic.fE = e/f;
577 verts[i].fConic.fF = f/f;
578 } 617 }
579 } 618 }
580 619
581 void add_conics(const SkPoint p[3], 620 void add_conics(const SkPoint p[3],
582 float weight, 621 float weight,
583 const SkMatrix* toDevice, 622 const SkMatrix* toDevice,
584 const SkMatrix* toSrc, 623 const SkMatrix* toSrc,
585 Vertex** vert, 624 Vertex** vert,
586 SkRect* devBounds) { 625 SkRect* devBounds) {
587 bloat_quad(p, toDevice, toSrc, *vert, devBounds); 626 bloat_quad(p, toDevice, toSrc, *vert, devBounds);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax); 683 (*vert)[2].fPos.set(SK_ScalarMax, SK_ScalarMax);
645 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax); 684 (*vert)[3].fPos.set(SK_ScalarMax, SK_ScalarMax);
646 } 685 }
647 686
648 *vert += kVertsPerLineSeg; 687 *vert += kVertsPerLineSeg;
649 } 688 }
650 689
651 } 690 }
652 691
653 /** 692 /**
693 * Shader is based off of Loop-Blinn Quadradic GPU Rendering
654 * The output of this effect is a hairline edge for conics. 694 * The output of this effect is a hairline edge for conics.
655 * Conics specified by implicit equation Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0. 695 * Conics specified by implicit equation K^2 - LM.
656 * A, B, C, D are the first vec4 of vertex attributes and 696 * K, L, and M, are the first three values of the vertex attribute,
657 * E and F are the vec2 attached to 2nd vertex attrribute. 697 * the fourth value is not used. Distance is calculated using a
698 * first order approximation from the taylor series.
658 * Coverage is max(0, 1-distance). 699 * Coverage is max(0, 1-distance).
659 */ 700 */
701
702 /**
703 * Test were also run using a second order distance approximation.
704 * There were two versions of the second order approx. The first version
705 * is of roughly the form:
706 * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2.
707 * The second is similar:
708 * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2.
709 * The exact version of the equations can be found in the paper
710 * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin
711 *
712 * In both versions we solve the quadratic for ||q-p||.
713 * Version 1:
714 * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as dervided frmm paper)
715 * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2 .0*gF2M);\n");
716 * Version 2:
717 * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2 .0*gF2M);\n");
718 *
719 * Also note that 2nd partials of k,l,m are zero
720 *
721 * When comparing the second order approximations to the first order the followi ng
jvanverth1 2013/07/31 18:41:40 More typos.
722 * results were found. Version 1 tends to underestimate the distances, thus it
723 * basically increases all the error that we were already seeing in the first or der
724 * approx. So this is probably not the one to use. Version 2 has the oppisite ef fect
725 * and tends to over estimate the distances. This is much closer to what we are
726 * looking for. It is able to render elipses (even thin) with out the need to ch op.
727 * However, it can not handle thin hyperbolas well and thus would still rely on
728 * chopping to tighten the clipping. Another side effect of the over estimating is
729 * that the curves become much thinner and "ropey". If all that was ever rendere d
730 * were "not too thin" curves and elipses then 2nd order may have an advantage s ince
731 * only one geometry would need to be rendered. However no benches were run comp aring
732 * chopped first order and non chopped 2nd order to compare speed.
733 */
660 class HairConicEdgeEffect : public GrEffect { 734 class HairConicEdgeEffect : public GrEffect {
661 public: 735 public:
662 static GrEffectRef* Create() { 736 static GrEffectRef* Create() {
663 GR_CREATE_STATIC_EFFECT(gHairConicEdgeEffect, HairConicEdgeEffect, ()); 737 GR_CREATE_STATIC_EFFECT(gHairConicEdgeEffect, HairConicEdgeEffect, ());
664 gHairConicEdgeEffect->ref(); 738 gHairConicEdgeEffect->ref();
665 return gHairConicEdgeEffect; 739 return gHairConicEdgeEffect;
666 } 740 }
667 741
668 virtual ~HairConicEdgeEffect() {} 742 virtual ~HairConicEdgeEffect() {}
669 743
(...skipping 12 matching lines...) Expand all
682 public: 756 public:
683 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 757 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
684 : INHERITED (factory) {} 758 : INHERITED (factory) {}
685 759
686 virtual void emitCode(GrGLShaderBuilder* builder, 760 virtual void emitCode(GrGLShaderBuilder* builder,
687 const GrDrawEffect& drawEffect, 761 const GrDrawEffect& drawEffect,
688 EffectKey key, 762 EffectKey key,
689 const char* outputColor, 763 const char* outputColor,
690 const char* inputColor, 764 const char* inputColor,
691 const TextureSamplerArray& samplers) SK_OVERRIDE { 765 const TextureSamplerArray& samplers) SK_OVERRIDE {
692 const char *vsCoeffABCDName, *fsCoeffABCDName; 766 const char *vsName, *fsName;
693 const char *vsCoeffEFName, *fsCoeffEFName;
694 767
695 SkAssertResult(builder->enableFeature( 768 SkAssertResult(builder->enableFeature(
696 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature)); 769 GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
697 builder->addVarying(kVec4f_GrSLType, "ConicCoeffsABCD", 770 builder->addVarying(kVec4f_GrSLType, "ConicCoeffs",
698 &vsCoeffABCDName, &fsCoeffABCDName); 771 &vsName, &fsName);
699 const SkString* attr0Name = 772 const SkString* attr0Name =
700 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); 773 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]);
701 builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffABCDName, attr0Name->c _str()); 774 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attr0Name->c_str());
702 775
703 builder->addVarying(kVec2f_GrSLType, "ConicCoeffsEF", 776 builder->fsCodeAppend("\t\tfloat edgeAlpha;\n");
704 &vsCoeffEFName, &fsCoeffEFName);
705 const SkString* attr1Name =
706 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[1]);
707 builder->vsCodeAppendf("\t%s = %s;\n", vsCoeffEFName, attr1Name->c_s tr());
708 777
709 // Based on Gustavson 2006: "Beyond the Pixel: towards infinite reso lution textures" 778 builder->fsCodeAppendf("\t\tvec3 dklmdx = dFdx(%s.xyz);\n", fsName);
710 builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n"); 779 builder->fsCodeAppendf("\t\tvec3 dklmdy = dFdy(%s.xyz);\n", fsName);
711 780 builder->fsCodeAppendf("\t\tfloat dfdx =\n"
712 builder->fsCodeAppendf("\t\tvec3 uv1 = vec3(%s.xy, 1);\n", builder-> fragmentPosition()); 781 "\t\t\t2.0*%s.x*dklmdx.x - %s.y*dklmdx.z - %s .z*dklmdx.y;\n",
713 builder->fsCodeAppend("\t\tvec3 u2uvv2 = uv1.xxy * uv1.xyy;\n"); 782 fsName, fsName, fsName);
714 builder->fsCodeAppendf("\t\tvec3 ABC = %s.xyz;\n", fsCoeffABCDName); 783 builder->fsCodeAppendf("\t\tfloat dfdy =\n"
715 builder->fsCodeAppendf("\t\tvec3 DEF = vec3(%s.w, %s.xy);\n", 784 "\t\t\t2.0*%s.x*dklmdy.x - %s.y*dklmdy.z - %s .z*dklmdy.y;\n",
716 fsCoeffABCDName, fsCoeffEFName); 785 fsName, fsName, fsName);
717 786 builder->fsCodeAppend("\t\tvec2 gF = vec2(dfdx, dfdy);\n");
718 builder->fsCodeAppend("\t\tfloat dfdx = dot(uv1,vec3(2.0*ABC.x,ABC.y ,DEF.x));\n"); 787 builder->fsCodeAppend("\t\tfloat gFM = sqrt(dot(gF, gF));\n");
719 builder->fsCodeAppend("\t\tfloat dfdy = dot(uv1,vec3(ABC.y, 2.0*ABC. z,DEF.y));\n"); 788 builder->fsCodeAppendf("\t\tfloat func = abs(%s.x*%s.x - %s.y*%s.z); \n", fsName, fsName,
720 builder->fsCodeAppend("\t\tfloat gF = dfdx*dfdx + dfdy*dfdy;\n"); 789 fsName, fsName);
721 builder->fsCodeAppend("\t\tedgeAlpha = dot(ABC,u2uvv2) + dot(DEF,uv1 );\n"); 790 builder->fsCodeAppend("\t\tedgeAlpha = func / gFM;\n");
722 builder->fsCodeAppend("\t\tedgeAlpha = sqrt(edgeAlpha*edgeAlpha / gF );\n"); 791 builder->fsCodeAppend("\t\tedgeAlpha = max(1.0 - edgeAlpha, 0.0);\n" );
723 builder->fsCodeAppend("\t\tedgeAlpha = max((1.0 - edgeAlpha), 0.0);\ n");
724 // Add line below for smooth cubic ramp 792 // Add line below for smooth cubic ramp
725 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2 .0*edgeAlpha);\n"); 793 // builder->fsCodeAppend("\t\tedgeAlpha = edgeAlpha*edgeAlpha*(3.0-2 .0*edgeAlpha);\n");
726 794
727 SkString modulate; 795 SkString modulate;
728 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 796 GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
729 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); 797 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() );
730 } 798 }
731 799
732 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { 800 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) {
733 return 0x0; 801 return 0x0;
734 } 802 }
735 803
736 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {} 804 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE {}
737 805
738 private: 806 private:
739 typedef GrGLEffect INHERITED; 807 typedef GrGLEffect INHERITED;
740 }; 808 };
741 809
742 private: 810 private:
743 HairConicEdgeEffect() { 811 HairConicEdgeEffect() {
744 this->addVertexAttrib(kVec4f_GrSLType); 812 this->addVertexAttrib(kVec4f_GrSLType);
745 this->addVertexAttrib(kVec2f_GrSLType);
746 this->setWillReadFragmentPosition();
747 } 813 }
748 814
749 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 815 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
750 return true; 816 return true;
751 } 817 }
752 818
753 GR_DECLARE_EFFECT_TEST; 819 GR_DECLARE_EFFECT_TEST;
754 820
755 typedef GrEffect INHERITED; 821 typedef GrEffect INHERITED;
756 }; 822 };
757 823
758 GR_DEFINE_EFFECT_TEST(HairConicEdgeEffect); 824 GR_DEFINE_EFFECT_TEST(HairConicEdgeEffect);
759 825
760 GrEffectRef* HairConicEdgeEffect::TestCreate(SkMWCRandom* random, 826 GrEffectRef* HairConicEdgeEffect::TestCreate(SkMWCRandom* random,
761 GrContext*, 827 GrContext*,
762 const GrDrawTargetCaps& caps, 828 const GrDrawTargetCaps& caps,
763 GrTexture*[]) { 829 GrTexture*[]) {
764 return HairConicEdgeEffect::Create(); 830 return caps.shaderDerivativeSupport() ? HairConicEdgeEffect::Create() : NULL ;
765 } 831 }
766 ///////////////////////////////////////////////////////////////////////////////
767 832
768 /** 833 /**
769 * The output of this effect is a hairline edge for quadratics. 834 * The output of this effect is a hairline edge for quadratics.
770 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first 835 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
771 * two components of the vertex attribute. Uses unsigned distance. 836 * two components of the vertex attribute. Uses unsigned distance.
772 * Coverage is min(0, 1-distance). 3rd & 4th component unused. 837 * Coverage is min(0, 1-distance). 3rd & 4th component unused.
773 * Requires shader derivative instruction support. 838 * Requires shader derivative instruction support.
774 */ 839 */
775 class HairQuadEdgeEffect : public GrEffect { 840 class HairQuadEdgeEffect : public GrEffect {
776 public: 841 public:
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
958 1023
959 /////////////////////////////////////////////////////////////////////////////// 1024 ///////////////////////////////////////////////////////////////////////////////
960 1025
961 namespace { 1026 namespace {
962 1027
963 // position + edge 1028 // position + edge
964 extern const GrVertexAttrib gHairlineAttribs[] = { 1029 extern const GrVertexAttrib gHairlineAttribs[] = {
965 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing}, 1030 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing},
966 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g} 1031 {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g}
967 }; 1032 };
968
969 // Conic
970 // position + ABCD + EF
971 extern const GrVertexAttrib gConicVertexAttribs[] = {
972 { kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBind ing },
973 { kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBindin g },
974 { kVec2f_GrVertexAttribType, 3*sizeof(GrPoint), kEffect_GrVertexAttribBindin g }
975 };
976 }; 1033 };
977 1034
978 bool GrAAHairLinePathRenderer::createGeom( 1035 bool GrAAHairLinePathRenderer::createGeom(
979 const SkPath& path, 1036 const SkPath& path,
980 GrDrawTarget* target, 1037 GrDrawTarget* target,
981 int* lineCnt, 1038 int* lineCnt,
982 int* quadCnt, 1039 int* quadCnt,
983 int* conicCnt, 1040 int* conicCnt,
984 GrDrawTarget::AutoReleaseGeometry* arg, 1041 GrDrawTarget::AutoReleaseGeometry* arg,
985 SkRect* devBounds) { 1042 SkRect* devBounds) {
(...skipping 18 matching lines...) Expand all
1004 IntArray qSubdivs; 1061 IntArray qSubdivs;
1005 FloatArray cWeights; 1062 FloatArray cWeights;
1006 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds, 1063 *quadCnt = generate_lines_and_quads(path, viewM, devClipBounds,
1007 &lines, &quads, &conics, &qSubdivs, &cWe ights); 1064 &lines, &quads, &conics, &qSubdivs, &cWe ights);
1008 1065
1009 *lineCnt = lines.count() / 2; 1066 *lineCnt = lines.count() / 2;
1010 *conicCnt = conics.count() / 3; 1067 *conicCnt = conics.count() / 3;
1011 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt + 1068 int vertCnt = kVertsPerLineSeg * *lineCnt + kVertsPerQuad * *quadCnt +
1012 kVertsPerQuad * *conicCnt; 1069 kVertsPerQuad * *conicCnt;
1013 1070
1014 target->drawState()->setVertexAttribs<gConicVertexAttribs>(SK_ARRAY_COUNT(gC onicVertexAttribs)); 1071 target->drawState()->setVertexAttribs<gHairlineAttribs>(SK_ARRAY_COUNT(gHair lineAttribs));
1015 GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize()); 1072 GrAssert(sizeof(Vertex) == target->getDrawState().getVertexSize());
1016 1073
1017 if (!arg->set(target, vertCnt, 0)) { 1074 if (!arg->set(target, vertCnt, 0)) {
1018 return false; 1075 return false;
1019 } 1076 }
1020 1077
1021 Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices()); 1078 Vertex* verts = reinterpret_cast<Vertex*>(arg->vertices());
1022 1079
1023 const SkMatrix* toDevice = NULL; 1080 const SkMatrix* toDevice = NULL;
1024 const SkMatrix* toSrc = NULL; 1081 const SkMatrix* toSrc = NULL;
(...skipping 24 matching lines...) Expand all
1049 } 1106 }
1050 1107
1051 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path, 1108 bool GrAAHairLinePathRenderer::canDrawPath(const SkPath& path,
1052 const SkStrokeRec& stroke, 1109 const SkStrokeRec& stroke,
1053 const GrDrawTarget* target, 1110 const GrDrawTarget* target,
1054 bool antiAlias) const { 1111 bool antiAlias) const {
1055 if (!stroke.isHairlineStyle() || !antiAlias) { 1112 if (!stroke.isHairlineStyle() || !antiAlias) {
1056 return false; 1113 return false;
1057 } 1114 }
1058 1115
1059 static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask | 1116 static const uint32_t gReqDerivMask = SkPath::kCubic_SegmentMask |
bsalomon 2013/07/31 18:48:33 I think this needs to be updated. Perhaps we shoul
egdaniel 2013/07/31 19:58:32 So we definitely needed to add the Conic mask (whi
1060 SkPath::kQuad_SegmentMask; 1117 SkPath::kQuad_SegmentMask;
1061 if (!target->caps()->shaderDerivativeSupport() && 1118 if (!target->caps()->shaderDerivativeSupport() &&
1062 (gReqDerivMask & path.getSegmentMasks())) { 1119 (gReqDerivMask & path.getSegmentMasks())) {
1063 return false; 1120 return false;
1064 } 1121 }
1065 return true; 1122 return true;
1066 } 1123 }
1067 1124
1068 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path, 1125 bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
1069 const SkStrokeRec&, 1126 const SkStrokeRec&,
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 kVertsPerQuad*n, // vCount 1238 kVertsPerQuad*n, // vCount
1182 kIdxsPerQuad*n, // iCount 1239 kIdxsPerQuad*n, // iCount
1183 &devBounds); 1240 &devBounds);
1184 conics += n; 1241 conics += n;
1185 } 1242 }
1186 } 1243 }
1187 target->resetIndexSource(); 1244 target->resetIndexSource();
1188 1245
1189 return true; 1246 return true;
1190 } 1247 }
OLDNEW
« no previous file with comments | « samplecode/SampleHairCurves.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698