pathfinder/shaders/gles2/ecaa-line.fs.glsl

68 lines
1.8 KiB
Plaintext
Raw Normal View History

// pathfinder/shaders/gles2/ecaa-line.vs.glsl
//
// Copyright (c) 2017 Mozilla Foundation
precision highp float;
uniform bool uLowerPart;
varying vec4 vEndpoints;
void main() {
// Unpack.
vec2 center = gl_FragCoord.xy;
vec2 p0 = vEndpoints.xy, p1 = vEndpoints.zw;
bool slopeNegative = p0.y > p1.y;
// Set up Liang-Barsky clipping.
vec4 pixelExtents = center.xxyy + vec4(-0.5, 0.5, -0.5, 0.5);
vec4 p = (p1 - p0).xxyy, q = pixelExtents - p0.xxyy;
// Use Liang-Barsky to clip to the left and right sides of this pixel.
vec2 t = clamp(q.xy / p.xy, 0.0, 1.0);
vec2 spanP0 = p0 + p.yw * t.x, spanP1 = p0 + p.yw * t.y;
// ...and to the bottom and top.
if (p.z != 0.0) {
vec2 tVertical = q.zw / p.zw;
if (slopeNegative)
tVertical.xy = tVertical.yx; // FIXME(pcwalton): Can this be removed?
t = vec2(max(t.x, tVertical.x), min(t.y, tVertical.y));
}
// If the line doesn't pass through this pixel, detect that and bail.
if (t.x >= t.y) {
bool fill = uLowerPart ? spanP0.y < pixelExtents.z : spanP0.y > pixelExtents.w;
gl_FragColor = vec4(fill ? spanP1.x - spanP0.x : 0.0);
return;
}
// Calculate A2.x.
float a2x;
if (xor(uLowerPart, slopeNegative)) {
a2x = spanP0.x;
t.xy = t.yx;
} else {
a2x = spanP1.x;
}
// Calculate A3.y.
float a3y = uLowerPart ? pixelExtents.w : pixelExtents.z;
// Calculate A0-A5.
vec2 a0 = p0 + p.yw * t.x;
vec2 a1 = p0 + p.yw * t.y;
vec2 a2 = vec2(a2x, a1.y);
vec2 a3 = vec2(a2x, a3y);
vec2 a4 = vec2(a0.x, a3y);
// Calculate area with the shoelace formula.
float area = 0.5 * (det2(a0, a1) + det2(a1, a2) + det2(a2, a3) + det2(a3, a4) + det2(a4, a0));
if (!slopeNegative)
area = -area;
// Done!
gl_FragColor = vec4(area);
}