68 lines
1.8 KiB
GLSL
68 lines
1.8 KiB
GLSL
// 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);
|
|
}
|