gecko-dev/gfx/webrender/res/ellipse.glsl
Kartikaya Gupta 9a69b9b3c6 Bug 1395237 - Update webrender to commit 81cba6b139c4c1061cab6a1c38acf2ae7f50445d. r=jrmuizel
Includes Cargo.lock updates.

MozReview-Commit-ID: GsEbblWnzT3
2017-08-31 14:09:26 -04:00

70 lines
1.8 KiB
GLSL

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef WR_FRAGMENT_SHADER
//
// Signed distance to an ellipse.
// Taken from http://www.iquilezles.org/www/articles/ellipsedist/ellipsedist.htm
// Note that this fails for exact circles.
//
float sdEllipse( vec2 p, in vec2 ab ) {
p = abs( p ); if( p.x > p.y ){ p=p.yx; ab=ab.yx; }
float l = ab.y*ab.y - ab.x*ab.x;
float m = ab.x*p.x/l;
float n = ab.y*p.y/l;
float m2 = m*m;
float n2 = n*n;
float c = (m2 + n2 - 1.0)/3.0;
float c3 = c*c*c;
float q = c3 + m2*n2*2.0;
float d = c3 + m2*n2;
float g = m + m*n2;
float co;
if( d<0.0 )
{
float p = acos(q/c3)/3.0;
float s = cos(p);
float t = sin(p)*sqrt(3.0);
float rx = sqrt( -c*(s + t + 2.0) + m2 );
float ry = sqrt( -c*(s - t + 2.0) + m2 );
co = ( ry + sign(l)*rx + abs(g)/(rx*ry) - m)/2.0;
}
else
{
float h = 2.0*m*n*sqrt( d );
float s = sign(q+h)*pow( abs(q+h), 1.0/3.0 );
float u = sign(q-h)*pow( abs(q-h), 1.0/3.0 );
float rx = -s - u - c*4.0 + 2.0*m2;
float ry = (s - u)*sqrt(3.0);
float rm = sqrt( rx*rx + ry*ry );
float p = ry/sqrt(rm-rx);
co = (p + 2.0*g/rm - m)/2.0;
}
float si = sqrt( 1.0 - co*co );
vec2 r = vec2( ab.x*co, ab.y*si );
return length(r - p ) * sign(p.y-r.y);
}
float distance_to_ellipse(vec2 p, vec2 radii) {
// sdEllipse fails on exact circles, so handle equal
// radii here. The branch coherency should make this
// a performance win for the circle case too.
if (radii.x == radii.y) {
return length(p) - radii.x;
} else {
return sdEllipse(p, radii);
}
}
#endif